Grunt.js: волшебная палочка для фронтенд-разработчика / Frontend


На сегодняшний день почти любой сайт, если он хоть немного сложнее домашней странички любимого кота, хранит под своим капотом кучу файлов с тоннами кода на css и javascript. Недобросовестные разработчики, ссылаясь на быстрый интернет пользователей, не стесняются выкатывать на продакшн свои творения в формате «as is», совсем не думая о том, что доля мобильного траффика растет как на дрожжах, а высокой скоростью мобильный интернет нас порадует еще очень нескоро. И это лишь один из поводов всерьез задуматься о грамотной сборке и оптимизации фронтенда. Нет, серьезно, берите свои многочисленные jquery-плагины, js-модули, виджеты, библиотеки, овощи там, рожь, пшеницу, вот это все, и минифицируйте, конкатенируйте, тестируйте, компилируйте, а такая магическая штука, как grunt.js, поможет в этом с помощью всего одной команды в консоли.

Как открыть для себя свободный от рутины мир? Наверняка ты уже прочитал мой предыдущий пост про stylus и, вдохновленный этой писаниной, установил на свой пипелац node.js и пакетный менеджер npm, в таком случае тебе достаточно выполнить в консоли следующую команду

npm install -g grunt

Затем идем в директорию проекта, создаем там файл grunt.js и начинаем волшебство с несложных заклинаний:
module.exports = function(grunt) {
	'use strict';

	grunt.initConfig({
		concat: {
			css: {
				src: [
					'src/css/*.css',
				],
				dest: 'css/styles.css'
			},
			js: {
				src: [
					'src/js/*.js'
				],
				dest: 'js/scripts.js'
			}
		},
		min: {
			dist: {
				src: [
					'js/scripts.js'
				],
				dest: 'js/scripts.min.js'
			},
		}
	});

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

};

Теперь выполняем в консоли команду grunt и, как ты уже догадался, получаем два файла — styles.css, полученный в результате конкатенации всех css-файлов из папки src/css/, и scripts.min.js, полученный в результате конкатенации всех js-файлов из папки src/js/ и последующей минификации.
Не хочется тратить время на компиляцию нового билда после каждого изменения? Правильно, есть же встроенный таск watch! Дописываем в наш grunt.js заветные строчки:
watch: {
	concat: {
		files: [
			'src/js/plugin.js'
		],
		tasks: 'default'
	}
}

Затем единожды запускаем в консоли grunt watch, и теперь при каждом изменении в файле src/js/plugin.js наши команды будут выполняться автоматически. Разумеется, можно настроить слежение за любыми файлами и выполнение любых задач.
Пока что мы использовали только встроенные таски grunt — min, concat и watch. Помимо них есть lint(проверка кода с помощью jshint), qunit(выполнение юнит-тестов QUnit), server(запуск сервера на node.js) и test(запуск юнит-тестов Nodeunit). Кроме того есть удобная консольная утилита grunt init, которая позволяет создавать проекты из шаблонов. Например, выполни в консоли grunt init:jquery и ты получишь заготовку под типовой jquery-проект.
В самом grunt-файле можно брать информацию из других json-файлов, использовать условную компиляцию, ссылаться с помощью шаблонов на настройки любого таска, создавать различные сборки проекта.
Ну и самое приятное — grunt очень легко расширяется, и добрыми людьми уже написаны сотни полезных плагинов на все случаи жизни: компиляция coffeescript, stylus, sass, jade, less, минификация css, инструменты для деплоя, оптимизация растровых изображений и векторной графики, склеивание спрайтов, livereload. В общем, есть где разгуляться.
Для установки стороннего плагина нужно выполнить в консоли команду
npm install [имя плагина]

А затем добавить в grunt.js строку
grunt.loadNpmTasks('[имя плагина]');

И все — можно добавлять новый таск.
Если же сторонние решения тебя не устраивают, или тебя посетила гениальная идея, как упростить жизнь себе и еще куче других фронтенд-разработчиков, то написать свой собственный таск также не составит особого труда — все ведь на твоем родном javascript. Достаточно потратить небольшое количество времени на изучение API от grunt, который довольно подробно задокументирован.
Лично я помимо встроенных тасков использую немного допиленный stylus, mincss и copy. Все они есть в наборе grunt-contrib.
Несколько ссылок по теме:

Примечание: при написании данного поста использовались примеры для grunt версий 0.3.x. На данный момент актуальной версией является уже 0.4.1, в которой произошли некоторые ощутимые изменения. Подробнее о миграции с 0.3 до 0.4 можно прочитать тут