合成可能性

合成可能性とは、小さな部品を組み合わせて大きなものを作る方法です。Voltron®のようなもの

Yeomanは、ジェネレータが共通の基盤の上に構築するための複数の方法を提供します。同じ機能を書き直す意味はないため、ジェネレータを他のジェネレータ内で使用するためのAPIが提供されています。

Yeomanでは、合成可能性は2つの方法で開始できます。

  • ジェネレータは、別のジェネレータと自身を合成することを決定できます(例:generator-backbonegenerator-mochaを使用します)。
  • エンドユーザーが合成を開始することもできます(例:Simonは、SASSとRailsを使用したBackboneプロジェクトを生成したいと考えています)。注:エンドユーザーが開始した合成は計画されている機能であり、現在は利用できません。

this.composeWith()

composeWithメソッドを使用すると、ジェネレータは別のジェネレータ(またはサブジェネレータ)と並行して実行できます。そのため、すべてを自分で行う代わりに、他のジェネレータの機能を使用できます。

合成する際には、実行コンテキストと実行ループを忘れないでください。特定の優先順位グループの実行では、合成されたすべてのジェネレータはそのグループの関数を実行します。その後、次のグループに対して繰り返されます。ジェネレータ間の処理順序は、composeWithが呼び出された順序と同じです。実行例を参照してください。

API

composeWithは2つのパラメータを受け取ります。

  1. generatorPath - 合成するジェネレータを指す完全なパス(通常はrequire.resolve()を使用)。
  2. 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-generatorgenerator-nodeで構成されています)を参照してください。

依存関係またはpeerDependencies

npmは3種類の依存関係を許可します。

  • dependenciesは、ジェネレータに対してローカルにインストールされます。使用される依存関係のバージョンを制御するための最適なオプションです。これが推奨されるオプションです。
  • peerDependenciesは、ジェネレータと並んで、兄弟としてインストールされます。たとえば、generator-backbonegenerator-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"