Pull to refresh

Миграция на Grunt v0.4

Reading time 5 min
Views 9K

Предисловие


18 февраля вышел релиз Grunt v0.4.0, с чем всех и поздравляю. Если вы еще не знакомы с Грантом — прошу пройти на официальный сайт или почитать ознакомительную статью на Хабре. Вкратце, Грант позволяет автоматизировать склеивание и минификацию js-файлов, запуск тестов, проверку кода с помощью JSHint и многое другое.

Данная статья — история миграции одного приложения с Гранта v0.3.9 на вышедшую v0.4.0. Версии несовместимы и переезд оказался не таким простым делом, как я изначально предполагал. Полная инструкция по миграции на английском находится здесь, она подробнее чем мое описание.

Зачем я использую Grunt


Как любому ленивому frontend-разработчику, мне нужен был инструмент, который автоматизирует рутинные задачи, позволяя сосредоточиться непосредственно на разработке. Так я нашел Грант, который делал за меня следующее:

  • компиляция stylus в css;
  • склеивание js-файлов;
  • проверка JavaScript линтером;
  • минификация склеенных js-файлов;
  • запуск unit-тестов (qUnit);
  • отслеживание изменений исходных файлов и автоматический перезапуск вышеперечисленных задач.


Все эти важные, но скучные задачи выполнялись одной командой:

→ grunt
Running "stylus:compile" (stylus) task
File 'css/styles.css' created.
 
Running "concat:js" (concat) task
File "project.js" created.
 
Running "lint:files" (lint) task
Lint free.
 
Running "min:js" (min) task
File "project.min.js" created.
Uncompressed size: 130468 bytes.
Compressed size: 20937 bytes gzipped (74246 bytes minified).
 
Running "qunit:all" (qunit) task
Testing index.html...............OK
>> 95 assertions passed (594ms)
 
Running "watch" task
Waiting...

Все задачи описываются в специальном грант-файле: grunt.js. Для вышеприведенного лога он схематично выглядит так:

module.exports = function(grunt) {
	grunt.initConfig({
		stylus: {
			// Компиляция Stylus в CSS
			compile: {
				options: {
					'compress': true,
					'paths': ['css/styl/']
				},
				files: {
					'css/styles.css': 'css/styles.styl'
				}
			}
		},
		concat: {
			// Склеивание js-файлов
			js: {
				src: [
					/* Здесь большой список файлов */
				],
				dest: 'project.js'
			}
		},
		min: {
			// Минификация
			js: {
				src: ['<config:concat.js.dest>'],
				dest: 'project.min.js'
			}
		},
		jshint: {
			options: {
				smarttabs: true
			}
		},
		lint: {
			// Проверка кода
			files: ['<config:concat.js.dest>']
		},
		watch: {
			// Перекомпиляция стилей при изменении styl-файлов
			stylus: {
				files: ['css/styl/*.styl'],
				tasks: 'stylus'
			},
			// Пересобирание скриптов и запуск lint при изменении исходных js-файлов
			js: {
				files: ['src/*.js'],
				tasks: 'concat lint'
			}
		},
		qunit: {
			// Запуск написанных qUnit-тестов
			all: ['../test/index.html']
		}
	});

	// Загрузка модуля для компиляции Стилуса
	grunt.loadNpmTasks('grunt-stylus');

	// Объявление тасков
	grunt.registerTask('default', 'stylus concat:js lint min:js qunit watch');
	grunt.registerTask('test', 'qunit');
};

Не буду подробно его разбирать, комментариев в коде должно быть достаточно.

Миграция


Переустановка модуля

Ранее установленный глобально модуль grunt (если таковой имеется) удаляем: npm uninstall -g grunt

И устанавливаем модуль интерфейса командной строки Гранта: npm install -g grunt-cli

Сам grunt теперь ставится локально в папку проекта: npm install grunt

Проверяем версии модулей:

→ grunt --version
grunt-cli v0.1.6
grunt v0.4.0

Глобально разрешено поставить модуль grunt-init, но в моем приложении он не используется.

Перед установкой убедитесь, что версия node.js >= 0.8.0.

Переименование грант-файла


mv grunt.js Gruntfile.js

Грант-файл со старым именем больше не поддерживается, без переименования увидим ошибку:

Fatal error: Unable to find Gruntfile.

В новое версии грант-файл можно писать на CoffeeScript: Gruntfile.coffee.

Установка плагинов

У обновленного Гранта больше нет встроенных задач, таких как concat, min, watch и др. Их необходимо добавлять в виде отдельных плагинов:

  • concat → grunt-contrib-concat
  • lint → grunt-contrib-jshint
  • min → grunt-contrib-uglify
  • qunit → grunt-contrib-qunit
  • watch → grunt-contrib-watch

Несложно заметить, что плагины Гранта имеют префикс grunt-contrib-.
Устанавливаем:

→ npm install grunt-contrib-concat
→ npm install grunt-contrib-jshint
→ npm install grunt-contrib-uglify
→ npm install grunt-contrib-qunit
→ npm install grunt-contrib-watch
→ npm install grunt-contrib-stylus

При установке рекомендуется использовать параметр --save-dev, чтобы автоматически обновлялись зависимости devDependencies в package.json.

Подключаем плагины в грант-файле:

grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-stylus');

Изменения в грант-файле

Методу registerTask теперь нельзя передать список задач одной строкой с пробелами-разделителями. Строкой разрешено передать только одну задачу: grunt.registerTask('test', 'qunit');

Для списка задач обязательно используем массив:

grunt.registerTask('default', ['stylus', 'concat:js', 'jshint', 'min:js', 'qunit', 'watch']);

Вместо деректив вида <config:concat.js.dest> теперь используем шаблоны: <%= concat.js.dest %>.

Задача lint с опциями jshint теперь объединена в задачу jshint, где сразу можно указать опции:

jshint: {
	options: {
		smarttabs: true
	},
	js: ['project.js']
}

Задачу min переименовываем в uglify. Вместо объектов src/dest используем объект files:

uglify: {
	js: {
		files: {
			'project.min.js': ['<%= concat.js.dest %>']
		}
	}
}

В задаче watch перечисляем выполняемые таски в виде массива:

watch: {
	js: {
		files: ['src/*.js'],
		tasks: ['concat', 'lint']
	}
}

На этом мой переезд был завершен, и Грант отработал без ошибок. Все изменения грант-файла собраны в этом шаблоне:

module.exports = function(grunt) {
	grunt.initConfig({
		// Компиляция Stylus в CSS
		stylus: {
			compile: {
				options: {
					'compress': true,
					'paths': ['css/styl/']
				},
				files: {
					'css/styles.css': 'css/styles.styl'
				}
			}
		},
		concat: {
			// Склеивание js-файлов
			js: {
				src: [
					/* Здесь большой список файлов */
				],
				dest: 'project.js'
			}
		},
		uglify: {
			// Минификация
			js: {
				files: {
					'project.min.js': ['<%= concat.js.dest %>']
				}
			}
		},
		jshint: {
			// Проверка кода
			options: {
				smarttabs: true
			},
			js: ['<%= concat.js.dest %>']
		},
		watch: {
			// Перекомпиляция стилей при изменении styl-файлов
			stylus: {
				files: ['css/styl/*.styl'],
				tasks: 'stylus'
			},
			// Пересобирание скриптов и запуск lint при изменении исходных js-файлов
			js: {
				files: ['src/*.js'],
				tasks: ['concat', 'lint']
			}
		},
		qunit: {
			// Запуск написанных qUnit-тестов
			all: ['../test/index.html']
		}
	});

	grunt.loadNpmTasks('grunt-contrib-concat');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-contrib-uglify');
	grunt.loadNpmTasks('grunt-contrib-qunit');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-stylus');

	// Объявление тасков
	grunt.registerTask('default', ['stylus', 'concat:js', 'jshint', 'uglify:js', 'qunit', 'watch']);
	grunt.registerTask('test', 'qunit');
};


Материалы по теме

Tags:
Hubs:
+27
Comments 13
Comments Comments 13

Articles