Yeoman でカスタムジェネレータを作る
yeoman について
アプリケーションの構成(ファイルやディレクトリ)をコマンド一発で作るツール。
簡単なジェネレーターを作る
以下のようなジェネレータを作る。
ジェネレータ名: sample
コマンド:
1)yo sample
2)yo sample:files
実行例は以下の通り。
# myappディレクトリを作成し、index.html, index.js, index.css を作成するコマンド $ yo sample myapp # 作成できたか確認 $ tree myapp myapp └── public ├── css │ └── index.css ├── index.html └── js └── index.js # home.html, home.js, home.css を作成するコマンド $ yo sample:files home # 作成できたか確認 $ tree . . └── public ├── css │ ├── home.css │ └── index.css ├── home.html ├── index.html └── js ├── home.js └── index.js
yeomanのインストール
始めに、yeoman の動作可能を準備する。
yeoman は node.js で動作するため、最初に node.js を以下からインストール。
node.js を準備できたら必要なパッケージをインストールする。
npm install -g yo generator-generator
yo は yeoman ジェネレータを実行するツールで、generator-generator はジェネレータの雛形を作成するツール。
ジェネレータの雛形作成
準備が整ったので、早速ジェネレータを作成する。
# generator-sample のディレクトリを作成 mkdir generator-sample cd generator-sample # generator-generator で雛形作成、いくつか質問されるので、適宜入力する。 yo generator
generator-sample の雛形が完成するので、ディレクトリ構成を確認してみます。
generator-sample/ ├── LICENSE ├── README.md ├── __tests__ │ └── app.js ├── generators │ └── app │ ├── index.js │ └── templates ├── node_modules │ └── (大量のディレクトリ) ├── package-lock.json └── package.json
雛形のうち、特に重要なのは generator/ ディレクトリ配下です。
ジェネレータは yo コマンドで呼び出された際、 generators/ 配下のディレクトリ名に基づいて動作します。
例えば "yo sample" コマンドを実行すると、 generator-sample/generators/app/index.js が実行されます。
ただし、app ディレクトリはデフォルトジェネレータと呼ばれる特殊なケースです。
普通は "yo sample:
メインジェネレータを実装する
では雛形が完成したので、早速ジェネレータを作ります。
まず、generator-sample/generators/app/index.js を以下のように修正します。
'use strict'; const Generator = require('yeoman-generator'); const makeDir = require('make-dir'); const path = require('path'); module.exports = class extends Generator { constructor(args, opts){ super(args, opts); // (1) コマンドライン引数を取得する this.argument('projectname', {type:String, required: true}); }; writing() { // (2) ディレクトリを作成する const root = this.options.projectname; makeDir.sync(root); makeDir.sync(root + '/public'); makeDir.sync(root + '/public/js'); makeDir.sync(root + '/public/css'); // (3) テンプレートを作成する const name = "index"; this.fs.copyTpl( this.templatePath('template.html'), this.destinationPath(root + '/public/' + name + '.html'), {name:name} ); this.fs.copyTpl( this.templatePath('template.js'), this.destinationPath(root + '/public/js/' + name + '.js'), {name:name} ); this.fs.copyTpl( this.templatePath('template.css'), this.destinationPath(root + '/public/css/' + name + '.css'), {name:name} ); // (4) .yo-rc.json をプロジェクトのルートフォルダに作成する this.destinationRoot(path.join(this.destinationRoot(), '/' + root)); this.config.save(); } };
順にコードを説明します。
(1) では、コマンドライン引数を取得します。
例えば "yo sample myapp" とすると、引数 projectname には "myapp" が代入されます。
(2) では、代入されたコマンドライン引数 projectname と同名のディレクトリを makeDir.sync(root) で作成しています。
さらに、その配下に "public", "public/js", "public/css" ディレクトリを作成しています。
(3) では、 this.fs.copyTpl コマンドでテンプレートファイル template.html を ejs形式で展開してコピーします。
現段階では、テンプレートファイルが存在しないため、 app/ 配下に templates ディレクトリを作成し、以下ファイルを配置して下さい。
<!-- generator-sample/generators/app/templates/templates.html --> <!DOCTYPE html> <html> <head> <title><%= name %></title> <meta charset='UTF-8'> <script src='./js/<%= name %>.js'></script> <link rel='stylesheet' href='./css/<%= name %>.css'></script> </head> <body> <h2><%= name %></h2> </body> </html>
// generator-sample/generators/app/templates/templates.js // <%= name %>.js
/* generator-sample/generators/app/templates/templates.css */ /* <%= name %>.css */
(4) では、 .yo-rc.json をプロジェクトのルートに作成しています。
.yo-rc.json はプロジェクトのルートを yeoman に記憶させるためのファイルです。
このファイルを作成しておけば、例えば public フォルダ内で "yo sample:files home としても正しい場所にファイルが作成されます。
これでメインジェネレーター機能は完成です。
最後に generator-sample/ に移動し、以下コマンドを実行して下さい。
$ npm link
これで generator-sample がローカルインストールされました。
ちなみに解除する場合は以下のコマンドで解除できます。
$ npm -g unlink generator-sample
では、任意のディレクトリに移動し、yo コマンドを確認して見て下さい。プロジェクト構成が "yo generate sample" と打つだけで作成されるはずです。
サブジェネレータを実装する
では次に "yo sample:files" を作成します。
まず、generators/files ディレクトリを作成し index.js を以下の内容で作成しましょう。
// generator-sample/generators/files/index.js 'use strict'; const Generator = require('yeoman-generator'); module.exports = class extends Generator { constructor(args, opts){ super(args, opts); this.argument('filename', {type:String, required: true}); }; writing() { const name = this.options.filename; this.fs.copyTpl( this.templatePath('template.html'), this.destinationPath('public/' + name + '.html'), {name:name} ); this.fs.copyTpl( this.templatePath('template.js'), this.destinationPath('public/js/' + name + '.js'), {name:name} ); this.fs.copyTpl( this.templatePath('template.css'), this.destinationPath('public/css/' + name + '.css'), {name:name} ); }
ディレクトリを作成する以外は app/index.js と一緒の内容ですので解説は省略します。
では、 templates/ ディレクトリを作成し、テンプレートを以下内容で作成しましょう。
<!-- generator-sample/generators/files/templates/templates.html --> <!DOCTYPE html> <html> <head> <title><%= name %></title> <meta charset='UTF-8'> <script src='./js/<%= name %>.js'></script> <link rel='stylesheet' href='./css/<%= name %>.css'></script> </head> <body> <h2><%= name %></h2> </body> </html>
// generator-sample/generators/files/templates/templates.js // <%= name %>.js
/* generator-sample/generators/files/templates/templates.css */ /* <%= name %>.css */
完成
これでジェネレーター完成です。
# myappディレクトリを作成し、index.html, index.js, index.css を作成 $ yo sample myapp # 作成できたか確認 $ tree myapp myapp └── public ├── css │ └── index.css ├── index.html └── js └── index.js # home.html, home.js, home.css を作成 $ yo sample:files home # 作成できたか確認 $ tree . . └── public ├── css │ ├── home.css │ └── index.css ├── home.html ├── index.html └── js ├── home.js └── index.js