Я стал замечать, что в последнее время build-системам стали уделять всё больше внимания, и, под влиянием этого, их в одночасье стало настолько много, что, честно говоря, уже всех и не упомнить. Последнее время у меня на слуху четыре системы: Grunt, Gulp, Brunch и Gear. Про все что-то где-то было написано, но ни разу не ставился вопрос о том, какие преимущества или недостатки они имеют друг перед другом? И именно поэтому я решил провести сравнительный анализ самых популярных build-систем(по версии google).
Но сперва надо определиться с критериями, по которым мы будем оценивать эти системы:
- Начало работы.
- Производительность. Никто не хочет ждать по минуте после изменения одного coffee-файла.
- Документация. Чем нагляднее и проще — тем лучше.
- Плагины. Ведь мы не хотим столкнуться с проблемой, когда мы начали использовать билд-систему, а в ней нет адаптера, скажем, для jasmine?
Теперь, я полагаю, с вводной частью можно покончить и приступить, наконец, к сравнению.
1. Начало работы
Grunt
Во многих статьях написано, что «писать для Grunt намного проще, чем потом это читать», и они во многом правы. Поэтому порог вхождения в эту билд систему чрезвычайно низок: достаточно прочитать одну страницу, чтобы иметь представление, как написать свой конфиг. Написание своих плагинов так же не занимает много времени и сил: всю систему вполне возможно изучить всего за несколько часов. Что касается порога вхождения в уже готовые проекты, то тут дела обстоят немного иначе, Gruntfile не так удобно читать, как писать. Представьте себе ситуацию, когда у вас к проекту подключены 20 плагинов и у каждого из них есть зависимости. Например, concat имеет смысл выполнять только после завершения работы плагина coffee и compass, а imagemin должен выполняться только после выполнения задачи copy. Это всё довольно проблематично отследить, даже если вы не используете шаблонизатор для описания ваших задач.
Gulp
Начало работы с Gulp такое же быстрое, как и с Grunt. Однако, оно лишено изъянов, которые мы обсуждали в начале работы с grunt для больших проектов, т.е. Gulp так же легко читать, как и писать, что делает его максимально располагающим к быстрому старту. Если же вы уже использовали какую-либо систему сборки, то время вхождения в Gulp уменьшится в разы.
Gear
Что касается творения от yahoo, тут все много печальней. Зайдя на сайт, мы видим громкое заявление о том, что система «easy to use», отлично! Соответственно, я полагаю, что сейчас мне коротко и ёмко расскажут об этой системе, как ею пользоваться и покажут простенький example. Итак, первое, что мы видим — это кусок кода и кнопочку «Run» в правом верхнем углу. Попробуем? А вот и нет! Вместо какого-то вразумительного результата мы увидим консоль ошибок. Лично мне это немного испортило первое впечатление. Ну да ладно, не об этом речь, идем дальше — установка gear.js
$ npm install gear gear-lib
Всё бы хорошо, но вот только есть одна неточность — если мы хотим использовать gear из CLI, то нам придется запускать установку с флагом -g, о чём нет ни единого упоминания. Что больше всего меня удивило — возможность установить gear «browser version». Как собирать coffee или scss из браузера я не догадался, тем более во всей доке нет ни одного слова про это. Идем дальше. А дальше мы видим два примера, при чем довольно странных примера — один иллюстрирует выполнение задач со множеством файлов, второй рассказывает нам, как запустить задачи асинхронно. Собственно, это все: никаких объяснений, ничего. Два голых куска кода — как хочешь, так и понимай. Думаю «ну ладно, наверно, дальше всё объяснят», но опять нет! Дальше под грифом «Документация» мы видим просто набор API. Как что-то собирать, основвываясь на этом API, какие гайдлайны использовать, где best practice — непонятно. В общем, никакого никакого «быстрого старта» ждать здесь не приходится.
Brunch
Тут все неплохо. Вполне себе понятное intro-видео, описывающее процесс создания приложения с помощью brunch и ссылка «за дополнительной документацией идите на github». Разворачивание проекта по видео занимает 30 секунд, при использовании генератора можно пощупать готовые решения и посмотреть best practice. В документации подробно описаны все возможные ситуации, и, хоть FAQ и не представляет из себя кладезь знаний, но ответы на самые частые вопросы найти все-таки можно. Brunch довольно своеобразная система, не похожая ни на что другое. Это не Gulp и уж тем более не Grunt(про Gear вообще молчу — это что-то с другой планеты). Brunch предоставляет все инструменты, которые могут потребоваться разработчику для автоматизации рабочего процесса, и делает весьма легко.
2. Производительность
Grunt
Grunt здесь прилично сдает свои позиции. Во-первых, использовать node.js и не использовать многопоточность — это просто грустно. Во-вторых, без дополнительных плагинов, грунт не умеет работать с кешированием измененных файлов. Т.е. если мы изменяем 1 из 10 000 файлов Coffee, то все десять тысяч будут пересобраны. Конечно, многопоточность можно привить с помощью grunt-concurrent, а работу с кешированием — с помощью grunt-newer, но это больше похоже на monkey-patch грунта, чем на полноценную реализацию. Но и это ещё не всё. Grunt имеет весьма кривой механизм для работы с потоками данных. Представьте, что нам сначало требуется собрать coffee, потом соединить все файлы, минифицировать их и прогнать тесты. Все эти действия связаны с одним и тем же набором файлов, однако грунт этого не понимает и использует для каждой задачи свой поток ввода-вывода, т.е. каждый раз заново считывает файлы и прогоняет для них ту или иную задачу, после чего записывает результат обратно на диск и так далее, пока все задачи не будут выполнены. Согласитесь, крайне затратные операции, особенно с учётом того, что мы можем использовать для этих же целей один поток ввода-вывода информации и все операции над одними и теме же файлами выполнять в оперативной памяти. Это бы позволило достичь намного лучшего результата по производительности.
Gulp
По сравнению с Grunt, данная система сборки заметно выигрывает в производительности. В отличии от своего предшественника, она поддерживает из коробки возможность работать в несколько потоков. Это дает весьма ощутимый прирост скорости. Так же стоит отметить, что Gulp использует всего один поток ввода/вывода при выполнении ряда задач с файлами. Это достигается несколько иным архитектурным решением, нежели использует Grunt. Если при создании Gruntfile вы будете указывать одни и те же маски для файлов в разных задачах, то в Gulpfile ситуация диаметрально противоположная: мы пляшем от файлов, а не от задач. Пример:
отрывок из Gruntfile:
...
concat: {
dist: {
src: ['src/**/*.js'],
dest: 'dist/app.js'
}
},
jshint: {
files: ['src/**/*.js']
}
...
отрывок из Gulpfile:
gulp.task('scripts', function() {
gulp.src(['app/src/**/*.js'])
.pipe(concat('dest.js'))
.pipe(jshint())
.pipe(gulp.dest('dist/build'))
})
Как мы видим, Grunt требует указания src для всех плагинов. Соответственно, это необходимо для того, чтобы при последовательном запуске, наша build-система могла понять, с какими файлами ей нужно производить манипуляции. В отличие от Grunt, Gulp требует указания src лишь для задачи, в рамках которой будут выполняться те или иные файлы, тем самым получая возможность осуществить процесс ввода-вывода всего один раз, что обеспечит нам максимальное быстродействие при сборке. Более того, как я уже сказал выше, Gulp позволяет работать с многопоточностью «из коробки», точнее, не то, чтобы «позволяет работать», а «работает по умолчанию в многопоточном режиме». Это значит, что по умолчанию все задачи будут запущены одновременно в разных потоках. Но что тогда делать, если наш concat должен выполниться только после coffee? В таком случае, мы можем просто создать зависимость! Это очень похоже на require.js, сами посудите:
var gulp = require('gulp');
// takes in a callback so the engine knows when it'll be done
gulp.task('one', function(cb) {
// do stuff -- async or otherwise
cb(err); // if err is not null and not undefined, the run will stop, and note that it failed
});
// identifies a dependent task must be complete before this one begins
gulp.task('two', ['one'], function() {
// task 'one' is done now
});
gulp.task('default', ['one', 'two']);
Как вам уже, скорее всего, стало понятно, задача two зависит от задачи one, и при запуске gulp, он выполнит сначало задачу one, и только после её выполнения перейдет к задаче two.
Так же, мы можем подключить к Gulp плагины gulp-cached и gulp-changed, чтобы иметь возможность кешировать неизмененные файлы и прогонять в рамках задач те файлы, которые подверглись изменению с момента предыдущего запуска.
Gear, Brunch: работают по принципу, идентичному Gulp — они максимальная параллелизация процессов. Удивительно, но остается только Grunt, которые не поддерживает этого «из коробки».
Вывод: На скромном бенчмарке(за основу взят стандартный Gruntfile, 10 JS, 10 CSS), выяснилось, что на моей моей машине, сортируя по производительности, мы можем наблюдать сл. результаты:
1-е место Gear(300ms)
2-е место Gulp(~+30ms)
3-е место Brunch(~+80ms)
4-е место Grunt(~+180ms)
3. Документация
Grunt
С этим у Grunt все хорошо. Документация компактная и полностью удовлетворяющая любым запросам. Всё необходимое для работы с системой можно найти на оф. сайте. Здесь нет никаких «но» и исключений — Grunt отлично задокументирован: просто и ёмко. Здесь вы сможете найти пример Gruntfile, все шаги для запуска и создания своей конфигурации. Разве что видео с наглядным примером нехватает, но это и не требуется при такой документации, как у Grunt.
Gulp
Gulp наступает на пятки Grunt: документация почти один-в-один повторяет документацию своего предшественника, разве что лежит не на сайта, а на github. Однако есть и различия: во-первых, в Get Started у Grunt лежит готовые Gruntfile, который можно сразу попробовать. Того же, к сожалению, не скажешь о Gulp. На этой странице вам просто объяснят, как его поставить и запустить. А дальше, мол, листайте доку и ищите, что вам нужно. И несмотря на то, что найти «то, что нужно» совершенно не составляет труда, это лишние телодвижения, которые явно не делают проще работу с этой системой. Понятное дело, что любой человек, который хоть раз держал в руках систему сборки представляет, что нужно делать, однако не будем забывать, что подобные разделы пишутся как раз для людей, которые слабо понимают, как с этим нужно работать. Во-вторых, нет четкого гайдлайна, как пользоваться этой системой и с какой стороны на неё смотреть. Я уверен, что люди, которые выберут Gulp в качестве своей первой системы для автоматизации сборки своих проектов, будут вынуждены искать информацию с примерами на сторонних ресурсах.
Gear
Всё не для людей. Документация этого проекта — простой набор API, мол, «что хочешь — то и делай». Никаких гайдлайнов или best practice вы здесь не найдете. Скажу более — в интернете, кроме mojito, эту систему не использует, наверное, никто. По крайней мере, я не нашел ни одного опровержения этой теории: ни одного сайта, который хотя бы косвенно упоминал использование этого сборщика.
Brunch
В git лежит 5 файлов, которые подробно описывают работу с системой и 1 FAQ. Информация простая, легкая к восприятию, но всё же хотелось бы чего-то большего. Информации в интернете про систему немного, поэтому вся экосистема brunch вертится вокруг его git репозитория и форума.
4. Плагины
Grunt: 2000+ плагинов, однако некоторая часть не обновлялась после релиза и/или не выпустила ни одного релиза
Gulp: 200+ плагинов, и количество стремительно увеличивается
Gear: А? Плагины? npmjs.org говорит, что кроме gear-lib с 5 плагинами, для этого сборщика вообще ничего не существует.
Brunch: 50+ плагинов, тенденция к очень медленному увеличению количества
Резюме
Grunt
Сложно предположить, в какую сторону сейчас может развиваться Grunt. Судя по последним changelog'ам, разработчики скорее просто хотят убрать все видимые огрехи, чем позаботиться об увеличении производительности. И лично меня это весьма сильно огорчает. Я пользуюсь этим инструментом достаточно давно, я привык к нему, но я вижу, как он потихоньку умирает, а на его место встают более свежие, оптимизированные сборщики. Конечно, как таковой, Grunt вряд ли умрет в ближайшее время. Но я чувствую сильный отток пользователей в сторону более современных систем.
Gulp
После Grunt, для меня это и правда «глоток свежего воздуха». Мне очень нравится направление развития этого проекта, если его авторы «не перегорят», то я думаю, что он вполне сможет заместить Grunt.
Gear
Исходя из всего, что я анписал про Gear, я сделал для себя вывод, что проект исключительно внутренний и выложен в open source скорее для поддержания имиджа компании, а-ля «смотрите, мы тоже сделали свою реализацию build-системы», чем для реального использования. Одно я могу сказать точно: чтобы пользоваться этой системой, вам потребуется всё писать самому. Мне хватило одного взгляда на Gearfile в каталоге самой библиотеки, чтобы понять, что я не буду этим заниматься. В конце концов, я хочу использовать build-систему для упрощения работы, а не наобарот. P.S. судя по всему, проект заброшен, т.к. последние 8 месяцев активности ноль.
Brunch
Хороший проект, с весьма качественное реализацией. Мне немного странно, что проект с таким потенциалом развивается так медленно. Темп разработки — наверно единственное, чего не хватает этому проекту.
P.S. Я с удовольствием приму ваши замечания и предложения по улучшению статьи, а так же буду благодарен любой информации, которая сможет дополнить данную её.
Автор: xamd