web-dev-qa-db-ja.com

プラグインにnpmのピア依存関係を使用するのはなぜですか?

例えば、どうしてGruntプラグインはgruntへの依存を "peer dependencies"と定義しているのですか?

grunt-plug/node_modulesでプラグインがGruntをそれ自身の依存関係として持つことができないのはなぜですか?

ピアの依存関係はここで説明されています: https://nodejs.org/en/blog/npm/peer-dependencies/

しかし、私は実際にはわかりません。

私は今のところAppGyver Steroidsを使用しています。これは、Gruntタスクを使用して、ソースファイルを/ dist /フォルダーにビルドしてローカルデバイスで提供するためのものです。私はnpmがかなり新しくてうんざりしているので、何が起こっているのかを完全に理解したいのです。

これまでのところ私はこれを得ます:

[rootfolder] /package.json npmに開発用のgrunt-steroids npmパッケージに依存するように指示します。

  "devDependencies": {
    "grunt-steroids": "0.x"
  },

はい。 [rootfolder]でnpm installを実行すると、依存関係を検出して[rootfolder]/node_modules/grunt-steroidsにgrunt-steroidsをインストールします。

それからNpmは[rootfolder] /node_modules/grunt-steroids/package.jsonと読み、それでgrunt-steroids自身の依存関係をインストールすることができます。

"devDependencies": {
    "grunt-contrib-nodeunit": "0.3.0",
    "grunt": "0.4.4"
  },
"dependencies": {
    "wrench": "1.5.4",
    "chalk": "0.3.0",
    "xml2js": "0.4.1",
    "lodash": "2.4.1"
  },
"peerDependencies": {
    "grunt": "0.4.4",
    "grunt-contrib-copy": "0.5.0",
    "grunt-contrib-clean": "0.5.0",
    "grunt-contrib-concat": "0.4.0",
    "grunt-contrib-coffee": "0.10.1",
    "grunt-contrib-sass": "0.7.3",
    "grunt-extend-config": "0.9.2"
  },

"dependencies"パッケージは[rootfolder]/node_modules/grunt-steroids/node_modulesにインストールされていますが、これは私にとって論理的なことです。

"devDependencies"はインストールされていません、それは私がちょうどgrunt-steroidsを使用しようとしていて、それを開発しようとしていないことを検出するnpmによって制御されると確信しています。

しかし、それでは "peerDependencies"となります。

これらは[rootfolder]/node_modulesにインストールされていますが、[rootfolder]/node_modules/grunt-steroids/node_modulesにインストールされていない理由はわかりません。他の不機嫌そうなプラグイン(または何か)は避けられますか?

164
Thomas Stock

TL; DR:[1] 公開されていない "private"の依存関係とは対照的に、peerDependenciesは消費するコードに公開されている(そして使用されると予想される)依存関係のためのものです。実装の詳細にすぎません。

ピアの依存関係が解決する問題

NPMのモジュールシステムは階層的です。より単純なシナリオの大きな利点の1つは、npmパッケージをインストールすると、そのパッケージが独自の依存関係を持ってくるので、そのまま使用できることです。

しかし、次の場合に問題が発生します。

  • プロジェクトと使用しているモジュールの両方が別のモジュールに依存しています。
  • 3つのモジュールはお互いに話さなければなりません。

例では

YourCoolProjectを構築していて、JacksModule 1.0JillsModule 2.0の両方を使用しているとしましょう。 JacksModuleJillsModuleに依存していますが、別のバージョンに依存しているとしましょう。1.0と言います。これら2つのバージョンが一致しない限り、問題はありません。 JacksModuleがサーフェスの下でJillsModuleを使用しているという事実は、単なる実装の詳細です。私たちはJillsModuleを2回バンドルしていますが、安定したソフトウェアを箱から出してすぐにそれを払うには少額の費用がかかります。

しかし今JacksModuleが何らかの方法でJillsModuleへの依存関係を公開するとどうなりますか。例えばJillsClassのインスタンスを受け付けます。ライブラリのバージョンnew JillsClassを使用して2.0を作成し、それをjacksFunctionに渡すとどうなりますか?すべての地獄が緩むでしょう! falseは実際にはjillsObject instanceof JillsClassバージョンのanotherjillsObjectのインスタンスであるため、2.0のような単純なものは突然JillsClassを返します。

ピアの依存関係がどのようにこれを解決するのか

彼らはnpmに言う

このパッケージが必要ですが、私のモジュール専用のバージョンではなく、プロジェクトの一部であるバージョンが必要です。

あなたのパッケージがプロジェクトにインストールされていることをnpmが見たときはその依存関係を持っていない、あるいはそれの互換性のないバージョン、それはインストールプロセス中にユーザーに警告します。

ピア依存関係をいつ使用するべきですか?

  • 他のプロジェクトで使用されるライブラリを構築しているときは、
  • このライブラリは他のライブラリを使用しています
  • あなたは、ユーザーがその他のライブラリでも作業することを期待/必要とします

一般的なシナリオは、より大きなフレームワーク用のプラグインです。 Gulp、Grunt、Babel、Mochaなどのことを考えてみてください。Gulpプラグインを作成する場合は、自分のプライベートバージョンのGulpではなく、そのプラグインがユーザーのプロジェクトで使用しているのと同じGulpで動作するようにします。


アノテーション

  1. 長すぎる;読んでいませんでした。長すぎると思われるテキストの短い要約を示すために使用されます。
329
Stijn de Witt

最初にこの記事をもう一度読むことをお勧めします。少し混乱しますが、winston-mailの例では、その答えを示しています。

たとえば、[email protected]"winston": "0.5.x"オブジェクトに"dependencies"を指定したとしましょう。これは、テスト対象の最新バージョンだからです。アプリ開発者としては、最新かつ最高のものが欲しいので、winstonwinston-mailの最新バージョンを調べて、それらをpackage.jsonに次のように入れます。

{
  "dependencies": {  
    "winston": "0.6.2",  
    "winston-mail": "0.2.3"  
  }  
}

しかし、今、npm installを実行すると、の予期しない依存グラフが表示されます。

├── [email protected]  
└─┬ [email protected]                
  └── [email protected]

この場合、いくつかの問題を引き起こす可能性があるパッケージの複数のバージョンを持つことが可能です。ピア依存関係により、npm開発者はユーザーが(ルートフォルダーに)特定のモジュールを持っていることを確認できます。しかし、ある特定のバージョンのパッケージを記述すると、他のバージョンを使用している他のパッケージで問題が発生する可能性があるという点では正しいと言えます。記事が述べているように、この問題はnpm開発者と関係がある。

1つのアドバイス:通常の依存関係とは異なり、は厳密な依存関係です。ピアの依存関係を特定のパッチバージョンに限定しないでください。

したがって、開発者はpeerDependenciesを定義するために semver に従うべきです。 GitHubでgrunt-steroidsパッケージの問題を開くべきです。

23
Fer To

peerDependenciesは、最も単純な例で説明しました。

{"name": "myPackage" "依存関係":{"foo": "^ 4.0.0"、 "react": "^ 15.0.0"}}

{"名前": "foo" "peerDependencies":{"反応": "^ 16.0.0"}}

myPackageでnpm installを実行すると、Reactバージョン^ 15.0.0 AND fooをインストールしようとしているためエラーが発生します。これは、React ^ 16.0.0とのみ互換性があります。

peerDependenciesがインストールされていません。

1