依存関係ツリー表面の論理構造と依存関係ツリーの実物理構造
依存関係ツリー表面の論理構造と依存関係ツリーの実物理構造は必ずしも同じではありません!
最初に 2 つのコマンドについて言及する必要があります:tree -d (linux) と npm ls (npm)
npm プロジェクトの下:
tree -d コマンド ツリー図付き 物理構造をリストしますプロジェクトの下のすべての依存関係の
npm lsコマンドプロジェクトの下のすべての依存関係の論理構造をツリー図にリストします
公式ドキュメントによると 例:
プロジェクトexample1 には、mod-a モジュールと mod-c モジュールという 2 つの依存モジュールがあります。
mod-a モジュールには、依存モジュール mod-b@1.0.0 モジュールがあります。
mod -c モジュールには、依存モジュール mod があります。 -b@2.0.0 module
tree -d と npm ls の実行結果は次のとおりです: (npm のバージョンは npm2 ではなく npm3 であることに注意してください)
まず、以下の赤いボックスの結果を見てください。これは、
「私たちの理解と最も一致している」
依存関係ツリーであるはずです。まず、プロジェクトの下に第 1 レベルの依存関係 (mod-a モジュールと mod-b モジュール) が形成されます。次に、これら 2 つのモジュールを親モジュールとして使用し、二次依存関係モジュール mod-b@1.0.0 と mod-b@2.0.0 を追加します
しかし! これは、物理的に形成された依存関係ツリーの外観ではありません。物理的に形成された依存関係ツリーは、上の赤いボックスです。
mod-a、mod-c、mod-b は実際には同じレベルの依存関係です。
なぜこのような依存関係ツリーが形成されるのかと疑問に思うかもしれません。 以下で説明していきます
【注意】: 以下の図はすべて依存関係ツリーの物理構造であり、論理構造ではありません
npmモジュールのインストールの仕組みについてちょっとした推測
モジュールをインストールする場合、考えられる方法は 2 つあります: フラットレベル インストールまたは ネストされた
インストール
(ここでは単なる推測と仮定です)
完全水平設置方式を採用? ——
無理
上記と同様の例を見てみましょう: プロジェクト APP の下に 2 つの依存モジュール A と B があります。A には依存モジュール Cv1.0 があり、B にも依存モジュール Cv2.0 があります。当然のことですが、インストール時に、同じノードモジュールの下に同時に存在することはできません。npm のメカニズムにより、依存するモジュールは 1 つのバージョンのみをインストールできます。そのうちの 1 つがもう 1 つを上書きします。 intecしかし、Cに従っているモジュールの1つのバージョンを1つのバージョンにインストールすると、モジュールAとモジュールBが互換性のないものになる可能性があります。上記の理由により、npm2 はネストされたインストール方法を選択しました -
npm2 のモジュール インストール メカニズム
npm2 は、ネストされたインストール方法を使用して、マルチレベルの依存モジュールをインストールします。
長所と短所
長所: 単一バージョンを使用する場合に存在する非互換性の問題を解決し、
複数バージョンの互換性を実現します
短所: それは、以下のように、同じモジュールの
大冗長性を引き起こす可能性があります:
上記の例を例として挙げると、次のような状況も合理的です:
私はそれを感覚で知っています。これは良い現象ではありません。では、依存関係間のマルチバージョン互換性を実現しながら、このモジュールの冗長性を減らすにはどうすればよいでしょうか?そこで、npm3 はいくつかの改善を行いました
npm3 のモジュールインストールメカニズム:
npm3 と npm2 の違いは主に二次モジュールのインストールに反映されます:
npm3 will
特定のレベルのすべてのモジュールを論理的および物理的にプロジェクトの最初のレベルに配置してみます。具体的には、次の 3 つの状況に要約できます。
1.特定の第 2 レベルのモジュールで、最初の
レベル
に同じ名前 のモジュールがまだないことが判明した場合、 第 2 レベルのモジュールを第 1 レベル
2 に置きます。特定の第 2 レベルのモジュールをインストールするときに、最初の レベル が同じ名前と同じバージョンのモジュール を持っていることが判明した場合、 そのモジュールを直接再利用します
3.確かな 2 番目のレベルのモジュールが見つかったとき、最初の レベル
が同じ名前で異なるバージョン で見つかった場合、そのモジュールは独自の親モジュールの下にのみネストできます
最初は少し分かりにくいかもしれないので、写真を見て話してみましょう!
1から始めましょう: 第2レベルのモジュールをインストールするときに、第1レベルに同じ名前のモジュールがないことがわかった場合は、第2レベルのモジュールを第1レベルに配置しますlevel
まず、上の例を単純化しましょう: 現在、プロジェクト APP の下には第 1 レベルの依存関係モジュール A が 1 つだけあり、その下に第 2 レベルの依存関係モジュール C がありますが、npm install すると依存関係がプロジェクトの下にインストールされます
npm3 の第 2 レベルのモジュール (C v1.0)、プロジェクトの第 1 レベルのディレクトリ (node_modules) に同じ名前のモジュールがない場合、は第 1 レベルのディレクトリにインストールされるため、その親モジュール A 同じレベルに従います。 これが、この記事の冒頭の依存関係ツリーの論理構造と物理構造が異なる理由です。それは言うことです:npm2で、依存性ツリーの論理構造はその物理構造と同じですnpm3、論理構造依存関係ツリーの物理的な構造とは異なる場合があります
2について話しましょう: 第2レベルのモジュールをインストールするときに、同じ名前と同じバージョンのモジュールが見つかった場合最初のレベルでは、そのモジュールを直接再利用できます
1 に基づいて、1 の例を前のより複雑なシナリオに戻します。プロジェクトの下に 2 つの依存モジュール A と B があります。 APP; A には別の依存モジュール Cv1.0 があり、B にも依存モジュール C v1.0 があります (2 つの C モジュールのバージョンは同じです)
npm2 の場合、2 つの C パッケージnpm3 では、モジュール A の下の C モジュールが最初のレベルにインストールされているため、モジュール B を同じレベルで再利用でき、同じ名前の C モジュールを使用できます。バージョン
npm3 が使用されます このアプローチは、npm2 の問題点を部分的に (部分的に) 解決します
[1、2 から 3 への移行] このセクションの冒頭で次のように述べました。 「npm3 は最善を尽くします」 「頑張ってください」
、でも私は言いました「頑張ってください」
。これは、npm3 が第 2 レベルの依存関係を第 1 レベルに置くことができないことも意味します。これに関しては、3:
を参照してください。最後に、3: セカンダリ モジュールをインストールするときに、最初のレベルで同じ名前でバージョンが異なるモジュールが見つかった場合、それらは以下にのみネストできます。独自の親モジュール
2 では、A と B が依存する 2 つの C モジュールは同じです。 しかし、2 つの C モジュールのバージョンが異なる場合はどうなるでしょうか? 、プロジェクトの npm インストール状況は次のとおりです:
npm3 では、B と A で必要な依存モジュールが異なるため (B の要件は C の v1.0 であり、 A の要件は C の v2.0 です) したがって、B は 2
のように A の下で C v1.0 モジュールを再利用することはできません (これを見ると、記事の冒頭の例についての疑問が解決されるはずです) 、この例とその例はほぼ同じです)
これを見ると、npm2 と npm3 のモジュールの動作メカニズムと、npm2 に対する npm3 の最適化について一般的に理解できます。 、しかし、これについて考えてください 質問: npm3 は、npm2 のモジュール冗長性の欠陥を極限まで最適化しましたか? ———答えは いいえです。下を見てください:
実際: npm3 にはまだモジュールの冗長性がある可能性があります。なぜなら、第 1 レベルのディレクトリにはすでに v1 があるからです。 .0 C モジュール、 したがって、すべての v2.0 は二次依存関係モジュール としてのみインストールできるため、次の状況が表示されます
そして、に示す特別なケースでは上の写真では、npm3とnpm2に違いはないようです
【トランジション】それで、これに対する解決策はありますか?もちろん、A モジュールの下の C v1.0 モジュールが C v2.0 に更新されると、npm dedupe を通じて C v2.0 の第 2 レベルの依存モジュールをすべて第 1 レベルに「リダイレクト」できます。ディレクトリ内の 0
npm dedupe を使用して冗長モジュールを削除します:
npm dedupe は何をしましたか? 削除できる冗長な第 2 レベルの依存モジュールを、同じ名前/バージョンの第 1 レベルのモジュールに「リダイレクト」できます
参考文献 npm 公式ドキュメント セクション 2 (npm の仕組み):
[暖かいリマインダー]: 分厚い本や退屈なドキュメントに匹敵する人気ブログはありません
【終了】
暗記する毎日小さな言葉10個、積み重ね重視!
memory: メモリ 依存関係: 依存関係 制約: 制約 デプロイ: デプロイメント パラメーター: パラメーター スコープ: スコープ
ecosystems: エコシステム プレフィックス: プレフィックス 事前: 優先順位/取り消し前: 取り消し
以上がnpm のモジュール インストール メカニズムの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。