7

my-module別のモジュールに依存するノードモジュールを開発していますother-moduleother-moduleしたがって、これは私のモジュールのpackage.jsonに明示的にリストされている依存関係です。

私のモジュールはdであるother-moduleだけで動作を変更するので、一度だけロードされることが重要であり、この唯一無二の「インスタンス」は、との両方を必要とするアプリケーション全体で参照されるものです。requireother-modulemyother

ノードのモジュールキャッシングポリシーに従ってこれが当てはまると期待していましたが、簡単なテストアプリを作成しているときに遭遇したのは次のとおりです。

前にmy-module編集npm installされた場合、後者は前者の依存関係として取り込まれます。その後、それをnode_modules階層にもう一度入れます。次に、モジュールが必要な場合、ノードはモジュールの「ローカル」コピーをロードし、アプリが2回目にそれをロードすると、ノードはそれを再度ロードします(今回は2番目のためにインストールされたバージョン)。これは明らかに意図した結果ではありません。 other-modulenpm installother-moduleother-modulerequirenpm install

それ以降my-modulenpm installedの場合、node_modulesのコピーは1つだけになり、テストアプリは期待どおりに機能します。 other-moduleother-module

この動作により、ノードの関連ポリシーをもう一度確認し、「モジュールキャッシングの警告」に出くわしたことを確認しました。

モジュールは、解決されたファイル名に基づいてキャッシュされます。モジュールは呼び出し元のモジュールの場所(node_modulesフォルダーからロード)に基づいて異なるファイル名に解決される可能性があるため、require('foo')が異なるファイルに解決される場合、常にまったく同じオブジェクトを返すという保証はありません。 。

この時点で、モジュールはnpm installsの順序に応じて期待どおりに動作する場合と動作しない場合があるようです。

私が見逃しているベストプラクティスはありますか?モジュールの動作方法を変更せずにこの混乱を回避する方法はありますか?

4

2 に答える 2

3

簡単な答え:できません。

ご指摘のとおり、ノードは最もローカルな場所から必要なモジュールをロードします。これは私が知る限り、パッケージマネージャーに固有のものであり、モジュールの正確な依存関係ツリーを気にする必要はありません。Nodeとnpmがそれを理解します。私の意見では、これは本当に良いことです。

モジュールに必要なものの正確なバージョンを要求する機会を与えることで、依存関係地獄を簡単に回避できます。

私があなたの質問を完全に理解していない限り、あなたがやろうとしていることは良いノードプラクティスではないと思います。モジュールがロードされ、ローカル変数に割り当てられます。グローバルな状態は避ける必要があります。これは、かなり厄介でテスト不可能なコードにつながる可能性があるためです。さらに、変更したモジュールを他の人のコードに挿入することに成功した場合、そのコードが引き続き機能するという保証はありません。これは、 StringArrayなどのJavaScriptの組み込みグローバルをハックして、悲惨なコードを作成することができた古いPrototype.js_時代のようになります。

ただし、この文章は1人の意見にすぎないことに注意してください。ここでそれ以上の回答が見つからない場合は、ノードのIRCチャネルなどの他の場所に質問を投稿してください。

于 2012-12-18T21:10:03.667 に答える
0

jestでテストを開発しているときに、同様の問題が発生しました。

次のステートメントを使用すると、同じモジュールを別のコンテキストで再度ロードできます。

jest.resetModules();
于 2017-01-13T02:28:25.290 に答える