では今回からgenerator-generatorが作成したプラグインを弄っていきます。この記事はYeomanのGeneratorを自作して作業効率を上げる!の続きでgenerator-generatorによってgenerator-sampleを作成していることが前提となります。
Generator作成のステップ
では作成されたgenerator-sampleディレクトリに移動します。
generatorはnpmのパッケージとして管理されるので、generator-generatorによって作成されたひな形もnpmのパッケージの構成をとります。
ステップ0:開発環境の整備
ローカル開発を始める前に、開発環境を整備する必要があります。
Yeoman wikiにあるように、npm link
をすることによって開発中のgeneratorをリアルタイムに実行することができます。
1 2 |
|
この状態で
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
で↑のようにsample generatorがyoコマンドから見えてればOKです。
これでローカル環境で開発中のgeneratorが使用できるようになりました。
ステップ1:Generatorの把握
まずはメインとなるapp/index.js
がどのようなことをやっているかを把握します。
app/index.js
のなかではSampleGeneratorを通してユーザとの対話とその挙動を定義します。
1 2 3 4 5 6 7 8 9 10 11 |
|
デフォルトではinitializing, prompting, writing, endが定義されています。
ほかにも定義があり、YeomanではこれらをRunning Contextと呼んでいます。
呼ばれるタイミングは決まっているので、それに合わせて各Running Contextを定義する、というのがYeomanの対話部分の実装方法です。
ステップ2:ディレクトリ構造の把握
ところでgenerator-generator
はどのようにgenerator-sample
を作成したのでしょうか?
generatorを作成するからには、ひな形を作りたいディレクトリ構造があるはずです。
挙動を考えるに、ユーザから入力された情報をテンプレートにはめ込んで出力しているのが濃厚に思えます。rubyで言えばerbみたいなものがどこかにありそうです。
予想通り、それらのテンプレートファイルはapp/templates
に存在します。generatorはひな形作成に使用するテンプレートファイルの置き場所をデフォルトでapp/templates
に定めています。
つまり、app/templates
以下に作成したいテンプレートファイルを置いて、app/index.js
で定義したgeneratorのユーザ入力を使ってひな形を作成する、というのがgeneratorの大まかな流れです。
ステップ3:対話の実装方法
では対話の実装方法について見ていきます。
ここが実装できるとひな形作成に必要な情報をユーザから入手できるようになります。
対話を実装するにあたり重要な部分はprompting
です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
重要なのは9行目のpromptsの定義からです。
generator-generator
が定義するひな形がありますが、その内容は
「’Would you like to enable this option?’と表示してsomeOptionというキーの値として入力値(true/false)を格納する」
です。簡単ですね。
でもちょっと待って下さい、僕達がやりたいのは大体ユーザから何らかの値や文字列を取得することではないでしょうか?
それも簡単です。prompts
に追加してみましょう。
1 2 3 4 5 6 7 8 9 10 |
|
無事質問を追加できたでしょうか?どこか適当なディレクトリを作って実行してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
↑の16行目が追加した質問です。どうでしょうか?
こんな感じでほしい情報を追加していきます。
ステップ4:テンプレートとの組み合わせ
さて、欲しい情報は取れました。では具体的にどうやってテンプレートにはめ込んでいくのでしょうか?
テンプレートに値を渡すのに重要なステップは
1 2 3 4 5 |
|
の部分です。
propsには対話で得た情報が格納されています。someOptionと同様に、ステップ3で追加した質問はprops.someValueに格納されています。
テンプレートに渡されるのはこのインスタンスです。
つまりpropsからこのインスタンスに値を保存することで、ユーザから得た情報をテンプレートに渡すことができます。
ではテンプレート側はどのように値を参照するのでしょうか?
erbのように<%= %>
で囲むだけです。拡張子も変える必要はありません。
例えば簡単なhtmlの中でsomeValueを参照したければ
1 2 3 4 5 |
|
みたいな感じです。
ステップ5:値のはめこみ
いよいよテンプレートに値をはめ込みます。
値をはめ込むのはwritingで行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
writingはObjectを値にとっていますが、キー名(ここではapp,projectfile)はなんでもいいと思います。
mkdirは名前通りディレクトリ作成。copyは「テンプレートを解釈した上で」第一引数のから第二引数へコピーします。つまりcopyがテンプレートに値をはめ込むわけですね。
YeomanのDocを見るとcopyを一度に行うdirectoryというメソッドも用意されています。
このあたりはソースであるyeoman/generatorを見るのも勉強になりますよ。
さて、これで基本的なgeneratorは作ることができるようになったと思います。
あとはnpmのパッケージと同様にnpmに登録すればパッケージとして公開することができます。
いかがでしたか?
説明すると長いですが、実際手を動かしてみると簡単だと思います。
これで少しでも定形作業が楽になればと思います。