Пишем генератор для Yeoman.io. Часть первая

в 18:19, , рубрики: javascript, node.js, nodejs, npm, yeoman, метки: , , ,

Доброго времени суток, читатели! В этом цикле статей я хочу описать опыт создания генератора для scaffolding системы Yeoman. Прежде всего, я был немного удивлён тем, что данная система и работа с ней не были описаны на хабре, разве что одно маленькое упоминание из далекого 2012 года: Yeoman.io. Как я уже написал выше, в данном цикле статей я буду рассматривать поэтапное создание yeoman-генератора для ваших проектов.

Yeoman-генератор(далее просто генератор) представляет собой npm-пакет, с помощью директив которого yeoman будет собирать наш каркас для будущего проекта. Я рассмотрю пример создания генератора для каркаса приложения, который я использую в своём нынешнем проекте + добавим простые элементы пользовательского интерфейса для возможности более гибкой настройки нашего приложения. Итак, начнём:

Начальные данные

Нам потребуется: машина с установленным nodejs, npm, yeoman и npm-пакетом generator-generator.
Далее, мы должны создать директорию, в которой будет располагаться наш генератор, например, как в моём случае, generator-puppeteer(ссылка на репозиторий будет немного позднее). Очень важно, чтобы ваша папка начиналась с префикса generator-, т.к. в противном случае, при начале работы, yeoman создаст папку, софрмированную по принципу generator-<имя генератора>, но обо всё по порядку.

Предположим, мы установили всё необходимое для начала работы над генератором, теперь создадим каркас генератора:

# Создадим директорию для нашего генератора
$ mkdir generator-puppeteer && cd $_

# Развернем каркас нашего генератора
$ yo generator

После двух вопросов про имя пользователя на github и названия генератора, yeoman разворачивает скелет нашего будующего генератора. Посмотрим, что мы тут имеем:

Директории:

app — директория, в которой будут находиться все наши файлы, связанные контентом проекта, например: bower.json, package.json, шаблоны всех наших страниц и т.п.
node_modules — директория с зависимостями генератора, продиктованными package.json, например chalk или mocha.
test — тут будут лежать все тесты для нашего генератора.

Файлы:

.editorconfig — конфиг для текстового редактора
.gitattributes — спецефические настройки директорий или файлов для git'а
.gitignore — список файлов и директорий, которые не будут проиндексированы git
.jshintrc — конфиг jshint
package.json — файл зависимостей генератора
README.md — файл описания проекта для github'а
.travis.yml — указание платформы для CI

Итак, скелет нашего генератора развёрнут.

Разработка генератора

На данном этапе мы имеем ничем не примечательный каркас генератора проекта. Теперь нам надо поставить вопрос, что должно отличать наш генератор от остальных. В своём примере, я буду разворачивать marionette с requirejs, sass + compass с возможностью скафолдить готовые архитектурные блоки(компоненты и модули).

Шаг 1 — Разбор архитектуры запускаемого файла

Лично у меня, когда я вижу незнакомую архитектуру, возникает закономерный вопрос: где находится точка входа в проект. В нашем случае — это файл index.js, находящийся в директории app. Рабоатет он следующим образом: сначало мы получаем доступ к файлу package.json и подписываемся на событие окончания инициализации. Если небыл передан флаг --skip-install, то после инифиализации будут установлены зависимости, прописанные в package.json и bower.json. Ничего сложного, верно? Теперь давайте попробуем закастомизировать стандартный UI скафолдера. Для этого нам придется изменить метод askFor — именно он вызывается первый после инициализации и отвечает за поллинг необходимой информации у пользователя(а так же рисует довольно симпатичный ASCII-арт). В данном методе используется имплементация библиотеки Inquirer, позволяющая создавать вопросы и получать информацию от пользователя. Давайте попробуем узнать у пользователя что-нибудь интересное, например название его приложения:

// Было
var prompts = [{
  type: 'confirm',
  name: 'someOption',
  message: 'Would you like to enable this option?',
  default: true
}];

this.prompt(prompts, function (props) {
  this.someOption = props.someOption;

  done();
}.bind(this));

// Стало
var prompts = [{
  type: 'prompt',
  name: 'appName',
  message: 'Could you tell me the name of your new project?',
}];

this.prompt(prompts, function (answers) {
  this.appName = answers.appName;

  done();
}.bind(this));

Больше информации вы сможете найти в их репозитории, на странице примеров. Использование данной библиотеки здесь будем максимально полезно, если вы решите предоставить пользователю возможность выбора дополнительных технологий, которые он возможно захочет включить в проект, например, можно спросить у пользователя, хочет ли он, чтобы в проект была включена возможность использовать bootstrap «из коробки». Как вы заметили, все переменные записываются как свойства экземпляра генератора — позднее, мы будем использовать их внутри шаблонов.

Шаг 2 — Скаффолдинг структуры приложения

Теперь давайте рассмотрим функцию app — сердце нашего генератора. Именно тут мы собираем каркас нашего приложения. Что же происходит в теле этой функции:

app: function () {
  this.mkdir('app');
  this.mkdir('app/templates');

  this.copy('_package.json', 'package.json');
  this.copy('_bower.json', 'bower.json');
}

Как мы видим, по умолчанию здесь всё весьма пресно: мы просто создаем 2 каталога и копируем 2 шаблона в директорию нашего проекта. Хотите больше?

Во второй части этого гайда мы продолжим работу с методом app, я напишу о создании архитектуры нашего приложения, мы подключим основные зависимости, научимся собирать шаблоны и попробуем запустить наш генератор!

Автор: xamd

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js