npmビルドプロセスと、package.jsonおよびpackage.lock.jsonのワークフローについて話す

一、起因

毎日のコードインスペクションで、ライブラリが実際にアップロードされていることがわかりましたpackage-lock.jsonこれは、バージョンのすべての依存関係とサブ依存関係を静的に記録するファイルです。このファイルのバージョンが最初に送信され、現在の9か月間に更新されていないため、この期間中に、フロントエンドライブラリは大小のpackage.json依存ライブラリでpackage-lock.jsonアップグレードされましたが、このファイルはアップグレードされていません。そこで、私はMRを作​​成し、ライブラリのファイルを削除しました。これは、元々は変更された開発バージョンでした。ただし、開発バージョンとビルドバージョンが同じマシン上にあるため、npm clean cache命令はマシン上のすべてのキャッシュパッケージをクリアし、リリースバージョンのビルドに同時に影響します。これによりnode_modulesライブラリのサブ依存関係がアップグレードされ、互換性の問題が発生します。リリース前夜に発見された問題ですので、影響は大きくなります。

2.分析

package.lock.json正確にはファイルとは何ですか?彼の役割は何ですか?私たちは図書館に行かなければなりませんか?次に、痛みを和らげ、npm installプロセスのpackage.lock.json効果に力を与えます。

1.セマンティックバージョン

semverpackage-lock.jsonを理解する必要がある前にプローブでそれはnpmの背後にある小さなヒーローです。npmがそれどのように使用するかは、ここから学ぶことができます要約すると、他のアプリケーションで使用できるアプリケーションを開発している場合、各アップグレードの変更がサードパーティの使用にどのように影響するかを説明する必要があります。これは、セマンティックバージョンが伝えたいことです。バージョンには3つの部分があります。それぞれメジャーバージョン、マイナーバージョン、およびチェックアップバージョンを指します。たとえば、メジャーバージョン、マイナーバージョンバージョンです。バージョンは機能に影響を与えません。マイナーバージョンの変更は、多くの場合、新しい機能を追加するためのものであり、使用には影響しません。ただし、メジャーバージョンの変更は、使用レベルでの非互換性をもたらすことが多く、さらに調整が必要です。(webpackがアップグレードされるたびに考えてください!)X, Y, Z1.2.312bugfix3bugfix

2. npmパッケージ管理

パッケージ管理を簡単にするためだけにnpm登場しました。プロジェクトには数百の依存関係があり、各依存関係には数百の依存関係があります。依存関係の地獄に陥らないようにするために、いくつかの単純なコマンドでnpmこれらの依存関係をインストールおよび管理できるため、時間を大幅に節約できます。

npmパッケージインストールして保存package.jsonすると、パッケージ名やバージョンなどの情報が自動的に追加されます。npmもちろん、バージョンのワイルドカードもサポートされています。npmデフォルトで最新バージョンをインストールし、バージョン番号の前に^記号を追加します。たとえば^1.2.12、これは最小1.2.12バージョンを使用する必要があることを示し、これより上では、同じ大きなバージョン番号のバージョンであれば問題ありません。結局、マイナーバージョンとバグ修正バージョンは使用に影響を与えないので、同じメジャーバージョンの上位バージョンを使用しても安全です。あなたは学ぶことができsemver、よりワイルドカードここでは、だけでなく、電卓。npmsemver

  • 記号^:インストールされているのがアプリケーションのバージョン以上であることを示しますが、同じメジャーバージョン番号が必要です。例:vuex: "^3.1.3"3.1.3およびそれ以上3.x.xが満たされています。
  • シンボル~:アプリケーションのバージョン以上にインストールされていることを示しますが、同じメジャーバージョン番号とマイナーバージョン番号が必要です。例:vuex: "^3.1.3"3.1.3およびそれ以上3.1.xが満たされています。
  • 署名なし:署名なしは、固定バージョン番号を意味します。たとえば、vuex: "3.1.3"これはインストールされている3.1.3バージョンである必要があります

3.なぜ必要なのかpackage-lock.json

npm installinputでありpackage.json、その出力はnode_modulesツリーです。理想的にnpm install纯函数、同じように動作し、package.json常に同じnode_modulesツリーに対してまったく同じツリー生成する必要があります。いくつかのケースでは、それは本当です。しかし、他の多くの状況では、これnpmは実行できません。以下の理由があります。

  • npmのバージョンが異なると、インストールアルゴリズムも異なります。
  • 前回のインストール以降、一部の依存関係がリリースされている可能性があるため、package.jsonのsemver-rangeバージョンに従って依存関係が更新されます。
  • 依存関係の新しいバージョンがリリースされた可能性があります。固定依存関係指定子( "^ 1.2.3"ではなく "1.2.3")を使用しても、サブ依存関係を修正できないため、更新されますアイテムのバージョン。
// package.json
"dependencies": {
    
    
    "packageA": "^2.1.0"
}

依存関係バージョンの更新により、いくつかの問題が発生する可能性があります。たとえば、A新しいプロジェクトが作成され、上記のpackage.jsonファイルが生成されますがA、依存関係をインストールする時期は比較的早いです。現時点packageAでは、最新バージョンは2.1.0コードと互換性があり、表示されませんbug後で、BクローンされたAプロジェクトはpackageA依存関係をインストールするときの最新バージョンです。バージョン2.2.0、セマンティクスに従ってnpmインストールされます2.2.0が、2.2.0バージョンAPIが変更され、コードにバグが生じる可能性があります。

これがpackage.jsonもたらす問題あり、同じコピーpackage.jsonが異なる時間と環境で異なる結果を生み出します。

理論上、この問題は発生しないはずnpmです。オープンソースの世界の一部として、リリースの原則にも従うためです。同じメジャーバージョン番号の新しいバージョンは古いバージョンと互換性があるはずです。つまり2.1.0アップグレードし2.2.0てもAPIは変更されません。

しかし、多くのオープンソースライブラリ開発者は、このリリース原則を厳密に遵守しなかったため、上記の問題が発生しました。

異なる環境node_modules同じものを生成するには、をnpm使用しますpackage-lock.jsonnpm installこれは、npm生成または更新されますそれが実行するたびにpackage-lock.json

4.異なるnpmバージョンでのnpm iのルール

  • npm 5.0.x版本package.json依存関係に更新があるかどうかに関係なく、それnpm iに基づいてpackage-lock.jsonダウンロードされますこのインストール戦略に対応して、誰かがこの問題(#16866)を提起し、それが5.1.0ポストバージョンルールに発展しました
  • 5.1.0版本后package.json新しいバージョンの依存関係にあるとき依存関係と更新の新しいバージョンをダウンロードするnpm installことを無視package-lock.jsonしますpackage-lock.jsonこのインストール戦略に対応して、誰かが問題を提起しました-#179795.4.2ポストバージョンルールを取得するには、npm寄稿者iarnaのコメントを参照してください
  • 5.4.2版本后
    • package.jsonファイルが1つしかない場合、操作npm iはそのpackage-lock.jsonファイルに基づいてファイルを生成します。このファイルは、今回のinstallスナップショットに相当しますpackage.json指定された直接依存バージョンだけでなく、間接依存バージョンも記録されます。
    • もし互換性のあるバージョン(バージョンバージョンの指定された範囲内で)、この時点でもかかわらず、新しいバージョンが存在し、実行がまだ基づいて実践シナリオ1 -ダウンロード。package.jsonsemver-range versionpackage-lock.jsonpackage-lock.jsonpackage.jsonpackage.jsonnpm ipackage-lock.json
    • 手動で変更した場合とし、バージョンと互換性がありません、実行時間は、互換性に更新されます練習シナリオ2 -バージョン。package.jsonversion rangespackage-lock.jsonnpm ipackage-lock.jsonpackage.json

注:作成された依存関係npm installpackage.jsonリストを読み、それpackage-lock.json使用して、インストールするこれらの依存関係のバージョンを通知します。依存関係が存在するpackage.jsonが存在しないpackage-lock.json場合、実行npm installにより、この依存関係の決定されたバージョンがpackage-lock.jsoninに更新され、他の依存関係のバージョンは更新されません。

5.練習

シーン1
// package.json
"dependencies": {
    
    
	"vue": "^2.0.0"
}

// package-lock.json
"dependencies": {
    
    
	"vue": {
    
    
		"version": "2.1.0",
		"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.1.0.tgz",
		"integrity": "sha1-KTuj76rKhGqmvL+sRc+FJMxZfj0="
	}
}

この場合package-lock.json、指定さ2.1.0^2.0.0た範囲、npm installインストールされているvue2.1.0バージョンで指定さています

シーン2
// package.json
"dependencies": {
    
    
	"vue": "^2.2.0"
}

// package-lock.json
"dependencies": {
    
    
	"vue": {
    
    
		"version": "2.1.0",
		"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.1.0.tgz",
		"integrity": "sha1-KTuj76rKhGqmvL+sRc+FJMxZfj0="
	}
}

この場合、package-lock.json指定され2.1.0ていない^ 2.2.0指定された範囲内で、npm install我々は続く^2.2.0最新インストールするには、ルールを2.6.10、バージョン、およびpackage-lock.jsonアップデートのバージョンを2.6.10

3.この例を引用する

この削除後package.lock.jsonの重要な理由はantdライブラリrc-paginationのサブ依存関係のアップグレードによるものでした。引用しantdたバージョン変更されていませんが、どちらも変更されています3.21.3しかし、従属関係の説明ではantd、次のようになります。

在这里插入图片描述

semverルールとは対照的に、依存コンポーネントのメジャーバージョンとマイナーバージョンは一貫している必要があり、改訂バージョンの要件はありません。ライブラリのコードは復元前に削除されpackage-lock.jsonrc-pagination依存関係の場合は1.20.12バージョンがダウンロードされ、削除package-lock.json後、新しくinstall生成package-lock.jsonされたロックバージョンは1.20.15次のようになります。

两个package.lock.json文件对比

然而,对于rc-pagination的版本升级,开发者没有遵循上述的semver规则,其中某个修订版本,有了不兼容修改,对于分页组件,pageSize必须默认传值,而不是由计算得出。故产品中所有依赖分页组件的模块,如果没有给pageSize传递默认值,通通报错白屏

四、镇定思痛

在这里,需要引出npm ci的概念:

关于npm ci
  • ciContinuous Integration,持续集成。
  • npm 版本至少是 v5.7.1
  • 此命令与 npm install 类似,不同之处在于它旨在用于自动化环境,例如集成测试环境、线上环境、或者您希望确保干净安装依赖项的任何情况。通过跳过某些面向用户的功能,它可以比常规的 npm install快得多。它也比常规安装更严格,它可以捕获由于本地环境的增量安装引起的错误或不一致。
  • npm ci是根据 package-lock.json去安装确定的依赖,package.json 只是用来验证是不是有不匹配的版本,假设package-lock.json 中存在一个确定版本的依赖 A,如果 package.json 中不存在依赖A 或者依赖 A 版本和lock中不兼容,npm ci就会报错。
npm cinpm install 差异
  • 项目必须存在 package-lock.jsonnpm-shrinkwrap.json
  • 如果 package-lock.json 中的依赖和package.json 中不匹配,npm ci会退出并且报错,而不是去更新 package-lock.json
  • npm ci只能安装整个项目的依赖,无法安装单个依赖。
  • 如果node_modules已经存在,它将在npm ci开始安装之前自动删除。
  • npm ci 永远不会改变package.jsonpackage-lock.json

我们目前的CI构建流程脚本中使用的一直是npm i。即使package.lock.json文件上库,对于大版本的依赖变动,我们安装的包也是不确定的。而且 npm i指令需要耗费大量的时间进行依赖检查,远程地址查询,本地依赖对比等操作,比较费时。对于这两点,我们完全可以通过package-lock.json 上库 + npm ci指令,控制库上每次自动化构建流程下载的依赖包固定不变。对于package.jsonpackage-lock.json文件的更新,由团队内统一的一个负责人负责,每次大版本变更,确定一个依赖的子依赖版本树,这样保证其他人不会改动到package-lock.json,且团队内部每个人下载的包固定不变。

おすすめ

転載: blog.csdn.net/qq_29722281/article/details/108550752