合成可能性とは、小さな部品を組み合わせて大きなものを作る方法です。Voltron®のようなもの
Yeomanは、ジェネレータが共通の基盤の上に構築するための複数の方法を提供します。同じ機能を書き直す意味はないため、ジェネレータを他のジェネレータ内で使用するためのAPIが提供されています。
Yeomanでは、合成可能性は2つの方法で開始できます。
- ジェネレータは、別のジェネレータと自身を合成することを決定できます(例:generator-backboneはgenerator-mochaを使用します)。
- エンドユーザーが合成を開始することもできます(例:Simonは、SASSとRailsを使用したBackboneプロジェクトを生成したいと考えています)。注:エンドユーザーが開始した合成は計画されている機能であり、現在は利用できません。
this.composeWith()
composeWithメソッドを使用すると、ジェネレータは別のジェネレータ(またはサブジェネレータ)と並行して実行できます。そのため、すべてを自分で行う代わりに、他のジェネレータの機能を使用できます。
合成する際には、実行コンテキストと実行ループを忘れないでください。特定の優先順位グループの実行では、合成されたすべてのジェネレータはそのグループの関数を実行します。その後、次のグループに対して繰り返されます。ジェネレータ間の処理順序は、composeWithが呼び出された順序と同じです。実行例を参照してください。
API
composeWithは2つのパラメータを受け取ります。
- generatorPath- 合成するジェネレータを指す完全なパス(通常は- require.resolve()を使用)。
- options- 合成されたジェネレータが実行された後に渡すオプションを含むオブジェクト。
peerDependenciesジェネレータと合成する場合
this.composeWith(require.resolve('generator-bootstrap/generators/app'), {preprocessor: 'sass'});
require.resolve()は、Node.jsが指定されたモジュールをロードする場所からのパスを返します。
注:1.0より古いバージョンのyeoman-generatorに基づいてジェネレータにargumentsを渡す必要がある場合は、options.argumentsキーとしてArrayを提供することで実行できます。
推奨される方法ではありませんが、composeWithにジェネレータの名前空間を渡すこともできます。その場合、YeomanはそのジェネレータがpeerDependenciesとして、またはエンドユーザーシステムにグローバルにインストールされているかどうかを調べようとします。
this.composeWith('backbone:route', {rjs: true});
ジェネレータクラスとの合成
composeWithは、最初の引数としてオブジェクトを受け取ることもできます。オブジェクトには、次のプロパティが定義されている必要があります。
- Generator- 合成するジェネレータクラス
- path- ジェネレータファイルへのパス
これにより、プロジェクト内で定義されたジェネレータクラス、または他のモジュールからインポートされたジェネレータクラスと合成できます。composeWithへの第2引数としてoptionsを渡すと、期待通りに動作します。
// Import generator-node's main generator
const NodeGenerator = require('generator-node/generators/app/index.js');
// Compose with it
this.composeWith({
  Generator: NodeGenerator,
  path: require.resolve('generator-node/generators/app')
});
実行例
// In my-generator/generators/turbo/index.js
module.exports = class extends Generator {
  prompting() {
    this.log('prompting - turbo');
  }
  writing() {
    this.log('writing - turbo');
  }
};
// In my-generator/generators/electric/index.js
module.exports = class extends Generator {
  prompting() {
    this.log('prompting - zap');
  }
  writing() {
    this.log('writing - zap');
  }
};
// In my-generator/generators/app/index.js
module.exports = class extends Generator {
  initializing() {
    this.composeWith(require.resolve('../turbo'));
    this.composeWith(require.resolve('../electric'));
  }
};
yo my-generatorを実行すると、次の結果になります。
prompting - turbo
prompting - zap
writing - turbo
writing - zap
composeWithの呼び出しを逆にすることで、関数呼び出しの順序を変更できます。
npmで公開されている他のパブリックジェネレータと合成できることに注意してください。
合成可能性のより複雑な例については、generator-generator(generator-nodeで構成されています)を参照してください。
依存関係またはpeerDependencies
npmは3種類の依存関係を許可します。
- dependenciesは、ジェネレータに対してローカルにインストールされます。使用される依存関係のバージョンを制御するための最適なオプションです。これが推奨されるオプションです。
- peerDependenciesは、ジェネレータと並んで、兄弟としてインストールされます。たとえば、- generator-backboneが- generator-gruntfileをピア依存関係として宣言した場合、フォルダツリーは次のようになります。- ├───generator-backbone/ └───generator-gruntfile/
- devDependenciesは、テストと開発ユーティリティ用です。ここでは必要ありません。
peerDependenciesを使用する場合は、他のモジュールも要求されたモジュールを必要とする可能性があることに注意してください。特定のバージョン(または狭いバージョンの範囲)を要求することで、バージョン競合が発生しないように注意してください。Yeomanでは、peerDependenciesを使用する場合は、常に利用可能なバージョン以上の(>=)または任意の(*)バージョンを要求することをお勧めします。例:
{
  "peerDependencies": {
    "generator-gruntfile": "*",
    "generator-bootstrap": ">=1.0.0"
  }
}
注:npm@3以降、peerDependenciesは自動的にインストールされなくなりました。これらの依存関係をインストールするには、手動でインストールする必要があります。npm install generator-yourgenerator generator-gruntfile generator-bootstrap@">=1.0.0"
