Сборка javascript проектов с помощью Grunt

Grunt – инструмент для сборки JavaScript проектов из командной строки. Молодой (зарелизился в январе 2012) и активно развивающийся(на данный момент для него написано уже 188 плагинов).

Благодаря тому, что grunt имеет готовый npm-пакет для node.js,  установка очень простая:

$ npm install grunt -g

Ставим grunt глобально, после чего нам доступна команда из консоли:

$ grunt --version
grunt v0.3.17

Далее необходимо инициализировать проект, для этого у нас есть команда grunt init:TEMPLATE, где TEMPLATE – один из шаблонов:

  • commonjs
  • jquery
  • node
  • gruntfile – только главный файл
  • gruntplugin

Перейдем в директорию где мы хотим создать grunt проект и выполним:

$ grunt init:jquery

после чего должно выдать серию вопросов о проекте(title, description, git-url…). После успешного прохождения этого квеста в выбранной директории появятся файлы сборщика.

Установим также PhantomJs, наличие которого предполагает grunt.

После чего можем смело запускать сборщик на выполнение:

$ grunt
Running "lint:files" (lint) task
Lint free.

Running "qunit:files" (qunit) task
Testing testproject.html....OK
>> 4 assertions passed (23ms)

Running "concat:dist" (concat) task
File "dist/testproject.js" created.

Running "min:dist" (min) task
File "dist/testproject.min.js" created.
Uncompressed size: 467 bytes.
Compressed size: 229 bytes gzipped (324 bytes minified).

Done, without errors.

– вот так вот он работает: проверил код(JSHint), запустил тесты(QUnit), соединил и сжал  файлы.

Чтобы рассмотреть инструкции по конфигурированию сборщика, проинициализируем новый проект:

$ grunt init:gruntfile

Он создаст только заготовку для главного файла(grunt.js). Откроем ее и посмотрим что внутри.

Начнем разбор с конца файла:

grunt.registerTask('default', 'lint qunit concat min');

Эта строчка говорит grunt какие задачи будут выполнены по умолчанию(т.е. запустив команду без параметров). Тут мы можем добавить свои варианты:

grunt.registerTask('prod', 'lint qunit concat min');
grunt.registerTask('test', 'lint qunit');

Возможные варианты заданий:

  • concat – конкатенация файлов
  • init – Generate project scaffolding from a predefined template.
  • lint – валидация файлов с помощью  JSHint.
  • min – сжатие файлов с UglifyJS.
  • qunit – Запуск QUnit юнит тестов на PhantomJS.
  • server – запускает статический веб сервер.
  • test – запуск юнит тестов на nodeunit.
  • watch – запуск заранее определенных заданий, для файлов из списка.

Ну а теперь последовательно по секциям конфига(по сути конфигурация для каждого задания):

meta - описание проекта, вспомогательная информация
lint/qunit/test/concat/min - список фалов, 
которые нужно отвалидировать(JSHint)/протестировать(qUnit)/протестировать(nodeUnit)/объединить/сжать(UglifyJS)
watch - список файлов и команды, которые необходимо выполнить, в случае изменения содержания файла
jshint - конфигурация JSHint
uglify - специфические настройки UglifyJS
server - пока не понятно зачем

Для каждой опции, где мы указываем список файлов существуют 2 подсекции: files и src. По умолчанию задание выполняется с командой files, но если мы хоти выполнить со списком файлов src, тогда стоит уточнить:

grunt.registerTask('build_src', 'lint:src qunit:src concat:src min:src');

Если встроенных заданий не хватает, можно писать свои и мотом подключать их с помощью методов:

grunt.loadTasks(ПУТЬ_К_ДИРЕКТОРИИ_С_ЗАДАНИЕМ);
grunt.loadNpmTasks(ИМЯ_ПЛАГИНА);

– второй вариант для дополнительных задач установленных через npm. Вот хорошая страничка, на которой перечислены самые распространенные варианты. Попробуем поставить requirejs:

npm install grunt-contrib-requirejs

и подключим в файл конфигурации:

grunt.loadNpmTasks("requirejs");

Внимание! тут есть специфика: модули установленные через npm будут подхватываться только если установлены в директорию c grunt. Подробно проблема описана вот тут.

Из основного это все.