Быстрая инициализация проекта
Представьте себе фронтенд-разработчика типичной среднестатистической компании, занимающейся веб-разработкой. У него часто возникает ситуация, когда каждый следующий проект начинается с тех же самых действий, что и несколько предыдущих. Можно даже сказать, что 90-95% проектов в рамках одной такой компании начинаются приблизительно с одних и тех же действий с точки зрения разработчика. Поработав так некоторое время многие начинают задумываться над вопросом оптимизации рабочего процесса: как можно избежать клонирования одной и той же структуры файлов и каталогов вручную? Как избежать поиска и загрузки новых версий используемых библиотек и не писать новые конфигурационные файлы для любимых менеджеров задач, препроцессоров и других инструментов? Как можно автоматизировать этот процесс? Как сделать инициализацию проектов более быстрой, гибкой и безболезненной? Давайте об этом поговорим.
Скаффолдинг
Наиболее часто употребляемый перевод для термина scaffolding — «инициализация проекта». На самом деле, обычно, смысл его немного глубже. Скаффолдинг — это процесс инициализации проекта, включающий развёртывание файловой структуры проекта и генерацию некоторого (иногда опционального) количества кода, требуемого пользователю. А скаффолдер — это инструмент, реализующий этот самый процесс. Таким образом, в результате скаффолдинга вы получаете заданную структуру проекта, код, сгенерированный вашим инструментом (скаффолдером), и, возможно, некоторые опциональные инструменты, вроде автоматизации задач, пакетных менеджеров, тестировщиков и т.п. Но, случается, что скаффолдер нужен только для создания определённой файловой структуры проекта без включения дополнительных компонентов в него.
Инструментарий
Удобный инструмент — это самое важное в вопросе эффективного скаффолдинга. Я открыл для себя Yeoman, и постараюсь открыть его для вас. А также предложу к рассмотрению ещё пару альтернативных скаффолдеров: Volo и grunt-init.
Yeoman
Yeoman — пожалуй, самый популярный в последнее время скаффолдер, поэтому о нём поговорим подробнее. На самом деле, сам Yeoman — это не просто скаффолдер, а целый набор инструментов, которые отлично дополняют друг друга в процессе скаффолдинга и гармонично сочетаются в процессе разработки. Yeoman «стоит на трёх китах», задающих тон рабочему процессу современных разработчиков: скаффолдер Yo, менеджер пакетов Bower и менеджер задач Grunt. При установке Yo вам будут установлены также Bower и Grunt, если они не были установлены ранее.
Генераторы
Генератор Yeoman — это npm-пакет с инструкциями и шаблонами для Yo, которые описывают инициализацию проекта: какие директории создать, какие файлы и куда копировать, каким образом обрабатывать шаблоны и куда их разместить после обработки. В Yeoman шаблоны обрабатываются с использованием библиотеки Underscore.js.
На момент написания статьи в npm-репозитории уже доступно для установки
более 300 генераторов. Устанавливаются они как
обычные npm-пакеты с использованием
команды npm install <generator-name>
.
В конце статьи я приведу небольшой список полезных генераторов.
Использование Yeoman
Самый простой способ понять, как именно инициализировать проекты с Yeoman — это начать его использовать. Я рассмотрю процесс скаффолдинга с использованием генератора generator-webapp и опишу использование каждого из трёх компонентов Yeoman.
Yo
Установка Yo выполняется командой:
npm install -g yo
После установки необходимо обзавестись генератором приложения,
которое вы хотите инициализировать.
Просмотреть список доступных для установки генераторов можно
по ссылке или выполнив поиск пакета в npm по ключу
«yeoman-generator»: npm search yeoman-generator
.
Если среди существующих генераторов нет ничего подходящего,
можно написать свой генератор. Но об этом позже.
Как уже было сказано, я опишу процесс скаффолдинга на примере генератора webapp. Для его глобальной установки выполните:
npm install -g generator-webapp
Теперь можно пробовать развернуть каркас будущего веб-приложения. Для запуска скаффолдинга в заранее созданной директории проекта выполните:
yo webapp
Генератор выполняет скаффолдинг по сценарию, который зависит от действий пользователя. Обычно на выбор предлагаются некоторые фундаментальные вещи, от которых будет существенно зависеть дальнейший процесс работы над проектом. В случае с webapp нам будет предложено выбрать, хотим ли мы в проекте использовать Bootstrap для Sass, RequireJS и Modernizr.
По завершении скаффолдинга вы получаете следующую структуру:
app/
node_modules/
test/
.bowerrc
.editorconfig
.gitattributes
.gitignore
.jshintrc
bower.json
Gruntfile.js
package.json
В директории app находится dev-версия вашего проекта — там содержатся все файлы в исходном состоянии, не прошедшие конкатенацию, минификацию и прочие обработки. Дальнейшая разработка проекта обычно не выходит за пределы этой директории.
Некоторые генераторы могут иметь опции, которые указываются непосредственно в командной строке в момент инициализации. Обычно они описаны в документации, поэтому читайте внимательно. Webapp имеет три опции:
--skip-install
— пропустить автоматический запуск установки пакетов Bower и npm после скаффолдинга.--test-framework <framework>
— по умолчанию установленmocha
. Может быть использован любой другой фреймворк для запуска тестов, вроде Jasmine.--coffee
— добавляет в проект поддержку CoffeeScript.
Grunt
Как вы уже поняли, конкатенация, минификация и
другие преобразования файлов, не требующие человеческого вмешательства
выполняются при помощи инструмента Grunt. Если вы до сих пор не
знакомы с ним, предлагаю для ознакомления прочесть
пост в блоге Артёма Сапегина,
вводный пост на сайте Smashing Magazine или
краткое руководство на официальном сайте.
Этого будет достаточно, чтобы начать его использовать. А пока вам необходимо
знать только то, что запуск задач Grunt происходит по команде
grunt [<задача>]
.
Генератор в процессе скаффолдинга устанавливает пакеты, необходимые
для выполнения задач Grunt. Большинство генераторов создают достаточно
объёмный Gruntfile.js
, имея в распоряжении «багаж» полезных задач.
Чтобы понять, какие задачи можно выполнять для проекта
достаточно заглянуть в Gruntfile.js
или выполнить grunt -h
для директории
с файлом Gruntfile.js
.
Webapp, например, имеет в качестве основных функциональных задач default
,
build
, test
, server
.
Задача server
выполняет очистку временной папки .tmp
в корне
проекта (создаёт её, если директория .tmp
отсутствует), обрабатывает
имеющиеся Sass-файлы и кладёт результат в .tmp/css
, запускает слежку за
изменением файлов в директории проекта, запускает сервер для обработки
статичных файлов и открывает страницу проекта в браузере с возможностью
запустить LiveReload, если у вас установлен плагин LiveReload для браузера.
Эта задача обычно запущена во время работы над проектом.
Задача test
собирает тестовую версию проекта,
запускает тестировщик Mocha или Jasmine, в зависимости от того, что было
выбрано при установке.
Задача default
, которая также запускается по команде grunt
, выполняет
проверку JS-файлов из директории app/scripts
на предмет ошибок
с помощью JSHint и запускает задачу test
.
Задача build
выполняет компоновку релизной версии проекта
с файлами, прошедшими конкатенацию, минификацию и переименование.
Релизная версия проекта располагается в директории dist
, которая будет
создана в корне проекта при первом запуске этой задачи.
Стоит отметить, что если вы не используете в проекте RequireJS и хотите
чтобы добавленные вами CSS-стили и JS-скрипты были доступны
для автоматической конкатенации и минификации (если вы
планируете использовать Grunt) их нужно записывать в index.html
указывая
тип файла и путь к нему в релизной версии проекта.
Важно понимать, что такое поведение — лишь частный случай генератора,
т.к. в Webapp используется задача useminPrepare
(плагин grunt-usemin), который берёт на
обработку файлы, описанные в HTML-файлах особым образом.
Например, добавляя в проект app/css/main.css
, который в релизной
версии будет расположен по пути dist/css/main.css
, мы должны добавить
в index.html
следующие строки:
<!-- build:css(.tmp) css/main.css -->
<link rel="stylesheet" href="css/main.css">
<!-- endbuild -->
Подобная ситуация и с JavaScript:
<!-- build:js js/vendor.js -->
<script src="bower_components/jquery/jquery.js"></script>
<!-- endbuild -->
Также можно осуществлять конкатенацию нескольких скриптов из dev- версии в один скрипт в релизной версии при помощи той же схемы:
<!-- build:js js/vendor.js -->
<script src="bower_components/jquery/jquery.js"></script>
<script src="bower_components/foundation/js/foundation/foundation.js"></script>
<!-- endbuild -->
Так нужно делать только в случае со всеми CSS-файлами и JS-библиотеками,
добавленными в проект вручную. Инструмент Bower, который будет рассмотрен
следующим, может автоматизировать процесс добавления библиотек в проект.
Если ваш Gruntfile.js
содержит задачу bower-install
, то можно
воспользоваться следующим алгоритмом:
-
убедиться, что в HTML-файле имеется следующие комментарии:
<!-- bower:js --> <!-- endbower -->
-
установить требуемую библиотеку, выполнив:
bower install jquery --save
-
вызвать задачу
bower-install
:grunt bower-install
Bower установит необходимую библиотеку, попытается записать файл библиотеки между комментариями из пункта 1 и сообщит вам, удалось ли ему это.
Bower
Третьим немаловажным компонентом Yeoman является Bower — менеджер
пакетов для веб-приложений. Этот инструмент упрощает поиск,
установку и обновление библиотек для вашего проекта. В процессе
скаффолдинга Bower позволяет
генератору загружать необходимые версии библиотек, зависимости которых
определены в файле bower.json
. Часто bower.json
представляет собой шаблон,
обрабатываемый генератором во время инициализации проекта. В таком случае
он способствует опциональной загрузке библиотек в процессе скаффолдинга.
Завершив скаффолдинг проекта,
вы сможете без лишних движений доставить требуемые библиотеки
при помощи Bower.
Всё, что для этого нужно: команды bower search [<ключевое_слово>]
и bower install <имя_пакета>
.
Установка пакетов идёт в директорию, путь к которой прописан
в конфигурационном файле .bowerrc
. C более тонкой настройкой Bower
вы сможете ознакомиться тут.
Bower работает с протоколами Git и HTTP(S) и способен устанавливать пакеты как из репозитория, так и из простого zip-архива.
Некоторые могут задуматься над вопросом: «Зачем нужен Bower, если есть npm?». Наиболее подходящее объяснение описано на сайте и состоит в том, что основное его предназначение — довольно простое управление отдельными пакетами с точки зрения фронтенд-разработчика за счет плоского дерева зависимостей и удобный API, который может быть использован для реализации более опциональных рабочих процессов. К тому же, Bower имеет отдельную от npm-плагинов директорию в проекте, что позволяет разработчику версионировать проект вместе с установленными пакетами и игнорировать локально установленные плагины для Node.js, которые зачастую занимают внушительное дисковое пространство.
Свой собственный генератор
Как уже было сказано ранее, уже существует более 300 генераторов Yeoman, доступных из npm-репозитория. Но может случиться так, что ни один из них не будет удовлетворять вашим потребностям. В таком случае вы всегда можете написать свой или внести изменения в существующий, если его лицензия позволяет это. Подробнее о том, как сделать свой генератор читайте здесь.
Полезные генераторы Yeoman
- Web App — генератор для инициализации веб-приложения на основе HTML5Boilerplate и опциональными компонентами. Рассмотрен в статье.
- AngularJS — генератор для инициализации веб-приложения на основе AngularJS. Также опционально устанавливает Twitter Bootstrap и дополнительные модули AngularJS, такие как angular-resource.
- Backbone — генератор для инициализации веб-приложения на основе Backbone. Также вы получаете доступ к нескольким суб-генераторам, которые могуты быть использованы для простого создания моделей (models), представлений (views), коллекций (collections) и т.д.
- Ember — генератор для инициализации веб-приложения на основе Ember.js.
- Mobile App — генератор для инициализации веб-приложений базирующихся на подходе mobile-first. Предоставляет возможность выбрать фреймворк из следующих: Twitter Bootstrap 3, TopCoat, Zurb Foundation и Pure.
- Jasmine — генератор, который инициализирует проект, использующий Jasmine в качестве фреймворка для тестирования проекта.
- H5BP — генератор для инициализации проекта на основе HTML5Boilerplate.
- Bootstrap LESS — генератор для инициализации проекта с использованием LESS-версии фреймворка Twitter Bootstrap.
Volo
Volo будет рассмотрен менее подробно, так как он обладает меньшими возможностями, в отличии от Yeoman. Volo, как нам сообщают на сайте разработчика:
Volo — это инструмент, который даёт возможность быстро создавать проекты, добавлять библиотеки и автоматизировать простые задачи используя Node.js и JavaScript.
Посмотрим, что он может:
Создание проекта
volo create [<имя_проекта>] [<репозиторий> | <ссылка_на_шаблон>]
Примеры:
volo create foo h5bp/html5-boilerplate/4.0.0
volo create foo http://mozilla.github.com/mortar/builds/app-stub.zip
Подробнее об инициализации проектов с Volo можно прочесть в этой статье.
Добавление библиотек в проект:
volo add jquery
volo add backbone
volo add requirejs/~2
volo add amdjs/backbone
Подробнее о добавлении библиотек
Для описания автоматизации процесса сборки проекта Volo использует
свой конфигурационный файл — volofile
. При этом, естественно,
необходимо предварительно установить node-плагины, используемые для
автоматизации задач таких, как jshint
или uglify-js
. Подробнее
об автоматизации с Volo можно узнать здесь.
Скаффолдинг с Grunt-init
Grunt-init — инструмент от разработчиков Grunt, позволяющий
разворачивать проекты, используя шаблоны.
То, что в Yeoman называлось генераторами, у grunt-init
называется шаблонами.
Для установки плагина вам необходимо выполнить:
npm install -g grunt-init
Использование grunt-init
концептуально ничем не отличается от других
скаффолдеров. Вам аналогично необходимо загрузить шаблон и запустить скаффолдер.
Однако, grunt-init
имеет специфику в установке шаблонов. Процесс установки
шаблона заключается в клонировании git-репозитория c исходным кодом шаблона
в директорию ~/.grunt-init/
. Выполнив клонирование шаблона, можно запускать
скаффолдер командой:
grunt-init <TEMPLATE_NAME>
Небольшой список доступных шаблонов можно найти на официальном сайте, а также в репозитории Артёма Сапегина.
Кроме того, вы можете написать свой шаблон. Подробные инструкции можно найти на том же официальном сайте и в блоге Артёма Сапегина.