Yeomanで、独自のジェネレータを作る方法。
ここでは yeoman-generator を使った方法について。
やり方
準備
yeoman と yeoman-generator をインストール
npm install -g yo generator-generator
(yeoman-generatorのバージョンは0.4.4)
ひな形の作成
ここからは ジェネレータ名を sample
とした場合
$ mkdir generator-sample
$ cd generator-sample
$ yo generator:app
色々聴かれるので適当に答えると以下のような
$ tree -L 2
.
├── README.md
├── app
│ ├── index.js
│ └── templates
│ ├── _bower.json
│ ├── _package.json
│ ├── editorconfig
│ └── jshintrc
├── node_modules
│ ├── chalk
│ ├── mocha
│ ├── yeoman-generator
│ └── yosay
├── package.json
└── test
├── test-creation.js
└── test-load.js
app/templates
以下に、generatorで生成するファイルの元を置き、
app/index.js
にgenerator起動時の処理を書いていくことになる。
app/templates/
ここに元となるファイルを置いておく。
アプリのルート以下を同じ構成で置いておく。
app/index.js
ここにyeoman-generator
で実行したときの挙動を実装していくことになる。
'use strict';
var util = require('util');
var path = require('path');
var yeoman = require('yeoman-generator');
var yosay = require('yosay');
var chalk = require('chalk');
var SampleGenerator = yeoman.generators.Base.extend({
init: function () {
this.pkg = require('../package.json');
this.on('end', function () {
if (!this.options['skip-install']) {
this.installDependencies();
}
});
},
askFor: function () {
var done = this.async();
// Have Yeoman greet the user.
this.log(yosay('Welcome to the marvelous Sample generator!'));
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));
},
app: function () {
this.mkdir('app');
this.mkdir('app/templates');
this.copy('_package.json', 'package.json');
this.copy('_bower.json', 'bower.json');
},
projectfiles: function () {
this.copy('editorconfig', '.editorconfig');
this.copy('jshintrc', '.jshintrc');
}
});
module.exports = SampleGenerator;
ジェネレータ実行した時にSampleGenerator
のメソッドが全部実行されていく。
上の場合ならinit
とaskFor
とapp
とprojectfiles
が順に実行されていく。
ただしconstructor
とinitialize
と頭に_
がついているメソッド名だった場合、スキップされる。
各メソッドの中で以下のようなプロパティやメソッドを使って
ファイルをコピーしたり、変換したりしていく。
以下、よく使いそうなもの一部抜粋。
プロパティ
-
appname
— String アプリケーション名 (カレントのディレクトリ名) -
log
— Function ログの出力
アクション
app/templates
以下にあるファイルをうつしたり、新しくディレクトリ作ったりする。
-
this.copy(src, dest)
— src から dest への ファイルのコピー。dest 省略の場合は、同じ名前になる。 -
this.directory(src, dest)
— src ディレクトリ以下のファイルをdestディレクトリにコピー。dest省略の場合、srcと同じディレクトリにコピー -
this.mkdir(dest)
— ディレクトリの作成 -
this.write(filepath, content, [writeFile])
— filepathにcontentを書き込む -
this.template(src, dest, [data], [options])
— srcファイルのテンプレート対応しつつ、destにファイルをコピーする。data が省略されている場合はthis
を参照。
例えば、
{
"name": "<%= appname %>"
}
となっている場合、this.template(‘_package.json’, ‘package.json’)
を実行すると、
<%= appname %>
が変数展開されて、package.json
に書き出される。
すべてはAPIドキュメント http://yeoman.github.io/generator/ に記載されている。
対話形式の取り入れ方
上のように対話形式で入力したい場合はthis.prompt(questions, callback)
を利用する。
これは中でinquirerというライブラリが使われているので、
questions
の形式は (https://github.com/SBoudrias/Inquirer.js#question) と同じ。
var prompts = [{
type: 'confirm’, // Yes or No
name: 'coffee',
message: 'Use CoffeeScript',
default: false
},
{
type: ‘input’, // テキスト入力
name: ’name',
message: 'What is your app name?',
default: 'sample'
}
];
this.prompt(prompts, function (props) {
this.coffee = props.coffee; // 結果がpropsに入っている
this.name = props.name;
done();
}.bind(this));
ここで値を取得して、テンプレート以下で条件分岐や
値を入れることで、任意のファイルをジェネレートすることが出来る。
yosay
yosayを使うとyeomanが喋ってくれる。
this.log(yosay('Yo!'));
参考
- Yeoman入門(第二部、generatorを作る) - from scratch — 動作確認方法やディレクトリ構造が詳しく書いてあります。
- Node.js - [日本語訳]Yeoman App Generatorsの書き方 - Qiita — より詳しい機能についてはこっち。