NPMのflatten,dedupeとshrinkwrap

5177 ワード

今日いくつかNPMの関连する问题に出会って、少し时间をかけてはっきりさせて、记录します.

NPMパケット依存フラット化(flatten)について


引き継いだプロジェクトではnpmパケットのネスト依存性を潰すパケットflatten-packagesが使用されている.この方面についてはこれまで知らなかったので、調査研究をした.

なぜ扁平化が必要なのか


初期には、npmパッケージは以下の形式で保存されていました.
.
|--app
    |--node_modules
       |--sub_module
          |--node_modules
             |--sub_sub_module
                |-- ... and so on

つまり、あなたのプロジェクトはパッケージAに依存しています.では、node_modulesにはAのフォルダがあり、このフォルダにはnode_があります.modules、すべてのAの依存はこのnodeを放しますmodulesでは、このように推定されます.npmのパケット依存は非常に深いフォルダ構造になり、Windowsシステムでフォルダを直接削除すると失敗することがあります.ファイルディレクトリがwindows制限の256文字を超えているためです.Git Bashとかrm -rfを開けることができます
これにより、異なるパケット(AとB)が同一のパケット(C)に依存する可能性があるという問題が生じる、このようにnpm installの場合、Aをインストールするときには1回Cをダウンロードし、Bをインストールするときには1回Cをダウンロードする.無形に多くの不要なダウンロードが多くなり、npm installの速度が遅くなる.
したがって、パケット依存性をフラット化する必要がある--重複する依存性をできるだけ統合し、パケット管理の速度を速める.

フラット化の方法


flatten-packages


flatten-packagesこのパッケージはこの問題を解決することができます.flatten-packagesを走ればいいです.
しかし、新バージョンのnpmでは自動フラット化処理が行われるため、flatten-packagesはもう役に立たず、このパッケージも更新を停止している.パケット衝突の解決においてもnpm dedupeに及ばない.関連Issue

npm 3の自動扁平化


npm第3版は自動的にパッケージの扁平化を行う.詳細はnpm v 3を参照し、flatを検索する.
npm 3はできるだけパケット依存性をフラット化し、ほとんどの場合、あなたの依存パケットはnode_に直接存在します.modules唯一の例外は、ある2つのパケットが互いに衝突するときである.

なぜパケット依存が衝突するのですか?


簡単な例は同じパッケージCである、AはC 1.0.0に依存し、BはC 2.0.0に依存する.このようにappがAとBに依存している場合は、node_に直接依存することはできません.modulesにはAとBの依存を同時に満たすバージョンCが入っています.ここのバージョン番号はSemVerです.

SemVer


SemVer(Semantic Versioning,セマンティックバージョン).
SemVerの最も基本的な構造はmajorです.minor.patch、例えば1.2.3.ここで、
  • majorはメインバージョン番号であり、後方互換性(すなわちbreaking change)がない場合、majorを更新する.
  • minorは次バージョン番号であり、後方互換性がある場合はminorを更新する.
  • patchはパッチ番号であり、後方互換性のあるバグfixがある場合にpatchを更新する.

  • npmはSemVerを使用してパッケージのバージョンをマークし、これらの構成はpackageに書き込まれている.json中
    固定バージョン番号を指定する以外は、package.jsonではバージョン番号の範囲を指定することもできる.
  • 1.2.x(x*で代用することもできる)は、>=1.2.0 <1.3.0
  • に相当する.
  • 1.x.x>=1.0.0 <2.0.0
  • に相当する.
  • 波線(Tilde)、~1.2.3>=1.2.3 <1.3.0に相当する、すなわちminorは増加できない.
  • ダッシュ、^1.2.3>=1.2.3 <2.0.0に相当する、すなわちmajorは増加できない.

  • 包脱重(dedupe)


    重さを落とすにはnpm dedupeを運転するだけです
    npm 3が自動的に扁平化された以上、なぜ重くする必要があるのか.このnpmは1篇の文章npm 3 Duplication and Deduplicationで説明して、私は翻訳しません.簡単に言えば、
  • 歴史的な理由により、ある2つのパケットAとBは同じパケットCの異なるバージョン1.0.0と2.0.0に依存し、この衝突によりCの依存は統合できない.
  • 以降のAとBのある更新により、同じバージョンのC 2に依存する.0.0、しかし依然としてあなたのappが直接C 1に依存するためです.5.0,AとBの依存を招くC 2.0.0はマージできず、AとBのディレクトリの下にしか保存できません.(質問:この時点でnpm dedupを実行するとどんな効果がありますか?)
  • 後にC 1に直接依存しました5.0 C 2に更新.0.0、これはあなたが3つの繰り返しのC 2を持つことを招きます.0.0,npm dedupeを運転する必要がある.(質問:なぜバージョンを更新できないときにdedupeを自動的に実行するのですか?)

  • パケット依存ロック(shrinkwrap/lock)


    package.jsonの依存パッケージのバージョン番号はバージョン範囲であるか、依存パッケージの依存がバージョン範囲を使用している可能性があります.これは、今日npm installにパッケージA 1がインストールされているという問題を引き起こす可能性があります.0.0、しばらくしてから同僚がnpm installを実行すると、A 1がインストールされる可能性があります.2.0、あなたたちの運行環境が全く同じではありません.パッケージ依存バージョン番号を完全にロックするにはshrinkwrap/lockが必要です.

    package-lock.json


    npm 5はpackage-lockを導入した.json、つまりnpm installを実行すると自動的にpackage-lockが生成されます.jsonファイルは、依存ツリーを記述するファイルであり、すべての依存バージョンやダウンロードアドレスをロックし、構造がはっきりしている(複雑なnode_modulesディレクトリ構造に比べて)利点がある.
    例package-lock.json
    {
      "name": "A",
      "version": "0.1.0",
      ...metadata fields...
      "dependencies": {
        "B": {
          "version": "0.0.1",
          "resolved": "https://registry.npmjs.org/B/-/B-0.0.1.tgz",
          "integrity": "sha512-DeAdb33F+"
          "dependencies": {
            "C": {
              "version": "git://github.com/org/C.git#5c380ae319fc4efe9e7f2d9c78b0faa588fd99b4"
            }
          }
        }
      }
    }
    

    package-lockがあればjson、インストールプロセスは次のようになります.
  • package-lock.jsonは依存パケットの木構造を再構築する.「resolved」フィールドがある場合は、そのフィールドが指すファイルを使用してファイルをダウンロードし、そうでない場合は「version」を使用します.
  • 最後に欠落依存パケットがある場合は、通常のpackageを用いる.jsonのインストール方法

  • 注意:npm installnpm rmnpm updateはpackage-lockを自動的に更新する.json. 更新したくない場合は、次のコマンドラインパラメータを使用します:--no-save:packageを更新しません.jsonもpackage-lockを更新しません.json --no-shrinkwrap:packageを更新します.json、package-lockを更新しません.jsonとnpm-shrinkwrap.json.
    npmはpackage-lockを非常に推奨している.jsonはバージョン管理を保存して、グループ内のすべてのメンバー、持続的な統合(Continuous Integration,CI)と配置環境が完全に一致した依存パッケージであることを確保する.[package-locks]

    npm-shrinkwrap.json

    npm shrinkwrapコマンドを使用してpackage-lock.jsonに基づいてnpm-shrinkwrapという名前を生成する.jsonのファイル
    package-lock.jsonとnpm-shrinkwrap.jsonの内容はまったく同じで、唯一の違いは、パッケージをパブリッシュするとき、package-lock.jsonは含まれないがnpm-shrinkwrap.jsonは一緒に発表されます.両方が同時に存在する場合、package-lock.jsonは完全に無視されます.

    リファレンス

  • Semver: A Primer
  • なぜ私はshrinkwrap(lock)
  • を使用しないのですか?
  • package-locks