Frontender Magazine

Быстрая инициализация проекта

Представьте себе фронтенд-разработчика типичной среднестатистической компании, занимающейся веб-разработкой. У него часто возникает ситуация, когда каждый следующий проект начинается с тех же самых действий, что и несколько предыдущих. Можно даже сказать, что 90-95% проектов в рамках одной такой компании начинаются приблизительно с одних и тех же действий с точки зрения разработчика. Поработав так некоторое время многие начинают задумываться над вопросом оптимизации рабочего процесса: как можно избежать клонирования одной и той же структуры файлов и каталогов вручную? Как избежать поиска и загрузки новых версий используемых библиотек и не писать новые конфигурационные файлы для любимых менеджеров задач, препроцессоров и других инструментов? Как можно автоматизировать этот процесс? Как сделать инициализацию проектов более быстрой, гибкой и безболезненной? Давайте об этом поговорим.

Скаффолдинг

Наиболее часто употребляемый перевод для термина scaffolding — «инициализация проекта». На самом деле, обычно, смысл его немного глубже. Скаффолдинг — это процесс инициализации проекта, включающий развёртывание файловой структуры проекта и генерацию некоторого (иногда опционального) количества кода, требуемого пользователю. А скаффолдер — это инструмент, реализующий этот самый процесс. Таким образом, в результате скаффолдинга вы получаете заданную структуру проекта, код, сгенерированный вашим инструментом (скаффолдером), и, возможно, некоторые опциональные инструменты, вроде автоматизации задач, пакетных менеджеров, тестировщиков и т.п. Но, случается, что скаффолдер нужен только для создания определённой файловой структуры проекта без включения дополнительных компонентов в него.

Инструментарий

Удобный инструмент — это самое важное в вопросе эффективного скаффолдинга. Я открыл для себя Yeoman, и постараюсь открыть его для вас. А также предложу к рассмотрению ещё пару альтернативных скаффолдеров: Volo и grunt-init.

Yeoman

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.

webapp-setup

По завершении скаффолдинга вы получаете следующую структуру:

app/
node_modules/
test/
.bowerrc
.editorconfig
.gitattributes
.gitignore
.jshintrc
bower.json
Gruntfile.js
package.json

В директории app находится dev-версия вашего проекта — там содержатся все файлы в исходном состоянии, не прошедшие конкатенацию, минификацию и прочие обработки. Дальнейшая разработка проекта обычно не выходит за пределы этой директории.

Некоторые генераторы могут иметь опции, которые указываются непосредственно в командной строке в момент инициализации. Обычно они описаны в документации, поэтому читайте внимательно. Webapp имеет три опции:

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, то можно воспользоваться следующим алгоритмом:

  1. убедиться, что в HTML-файле имеется следующие комментарии:

    <!-- bower:js -->
    <!-- endbower -->
    
  2. установить требуемую библиотеку, выполнив:

    bower install jquery --save
    
  3. вызвать задачу 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

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>

Небольшой список доступных шаблонов можно найти на официальном сайте, а также в репозитории Артёма Сапегина.

Кроме того, вы можете написать свой шаблон. Подробные инструкции можно найти на том же официальном сайте и в блоге Артёма Сапегина.

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Денис Демченко

Комментарии (21 комментарий, если быть точным)

Автар пользователя
sapegin

grunt-init — это совсем не плагин, а отдельный инструмент, довольно косвенно связанный с Грантом. И сейчас я неспешно перехожу на генераторы Йомена, они всё-таки мощнее, хотя и кажутся сложнее поначалу.

P. S. Спасибо за ссылки!

Автар пользователя
mikeyakimenko

Я лично совсем не в восторге от хваленого grunt'a. Не всегда он полезен и удобан. Йомена не пробовал. Но уверен что это аналогия :)

Автар пользователя
sapegin

@macgera Грант прекрасен и удобен, и я использую его во всех проектах последние года два. Из Йомена мне нужен только yo, он тоже офигенный, но довольно трудно разобраться, как писать свои генераторы.

Что такое «анология» я, честно, не знаю :-)

Автар пользователя
mikeyakimenko

@sapegin черт! ) Я как всегда)) Спасибо, исправил :) Но эти все скафолдеры... нет. Мне не удобны. Заметь, я не утверждаю что они безполезны и плохие, в принципе, я говорю что лично мне не удобны. :)

Автар пользователя
sapegin

@macgera Может быть ты не распробовал / не нашёл идеальный для тебя инструмент? Я до гранта довольно мало всякого автоматизировал, а многого не делал вообще почти никогда, потому что было слишком сложно и нудно.

Автар пользователя
mikeyakimenko

Ну сложно.. нет. Тут скорее всего просто потеря времяни. Это почти как и с BEMом. Иногда процесс инициализации и чрезмерная автоматизация/оптимизация – вредны)

Автар пользователя
sapegin

@macgera Потеря времени — это как раз руками всё копипастить :-)

Автар пользователя
kipruss

В процессе обновления Yeoman с версии 0.9.6 до 1.0.0 наша команда испытала некоторые сложности, что привело к временному переходу на http://middlemanapp.com/ который в итоге превратился в постоянный. Хотя тут надо учесть, что зачастую результаты работы копируются в ROR-проект, поэтому нам и понравился Middleman.

Автар пользователя
gladkih

@macgera, инициализация и настройка гранта требует немного времени. раз сделав и настроив его я сделал шаблон и теперь при начале работы нового проект мне необходимо только поправить название в пэкидж файл и npm install. Все готово к работе :-)

Автар пользователя
mikeyakimenko

Да может и так.. Но как-то пока что н прижился. А вот mm хочу попробовать.

Автар пользователя
Grawl

Библиотека шаблонов пока только одна – для Yeoman. Не нашёл ни для grunt-init, ни для volo.

Автар пользователя
lancedikson

@Grawl, что вы имеете в виду под библиотекой шаблонов?

Автар пользователя
Grawl

@lancedikson ну вот как Yeoman Community Generators

Автар пользователя
lancedikson

@Grawl, ну, в общем-то, да. Но, вот небольшой набор шаблонов для volo.js.

Автар пользователя
Grawl

@lancedikson что ж, пожелаем ему удачи, а я пока с упованием смотрю на MiddleMan. Благодарю @kipruss за наводку!

Автар пользователя
murashki

Несколько не понял. Скафолдинг это же когда есть БД, есть предлагаемая система и тут хлоп! Сразу тебе интерфейс для редактирования данных. Если так, то где формы, списки там всякие и т.д?

Автар пользователя
lancedikson

@murashki, во фронтенде этот термин означает именно то, что описано в этом параграфе.

Автар пользователя
sapegin

@murashki @lancedikson Собственно термин ознаает везде одно и то же, но в одном случае создаются файлы, а в другом база данных. Что нужно для инициализации проекта, то и создаётся скаффолдером.

Автар пользователя
lancedikson

@murashki @sapegin, именно :)

Автар пользователя
LeusMaximus

Поскажите, как сейчас обстоят дела с генераторами? Кто что использует? Какой сейчас наиболее актуальный?

Автар пользователя
iamstarkov

@LeusMaximus yeoman всё ещё на коне