「npm install」がpackage-lock.jsonを書き換えるのはなぜですか?


614

最近npm @ 5にアップグレードしました。これで、package.jsonのすべてを含むpackage-lock.jsonファイルができました。私が実行すると、依存関係バージョンがロックファイルからプルされ、node_modulesディレクトリに何をインストールする必要があるかが決定されると思います。奇妙なのは、それが実際に私のpackage-lock.jsonファイルを変更して書き直してしまうことです。npm install

たとえば、ロックファイルにはtypescriptがバージョン2.1.6に指定されていました。その後、npm installコマンドの後、バージョンは2.4.1に変更されました。これは、ロックファイルの目的全体を無効にするようです。

何が欠けていますか?npmで実際にロックファイルを尊重するにはどうすればよいですか?


4
これはあなたの質問に答えないので、うまくいけばコメントは大丈夫ですが、ヤーンを見てください。切り替えには1時間もかかりませんでした。
KayakinKoder 2017

4
同じ問題ですが、糸を使用していますgithub.com/yarnpkg/yarn/issues/570(非常に有益
Yves M.

2
同じ問題が発生しています。私はpackage-lock.json、私が実行したときに再生しますnpm install。これはnpmバグのようなにおいがします。独自のレジストリを使用していますか?
HaNdTriX 2017


@YvesM。--no-saveロックファイルの変更を防ぎますが、OPが言及する間抜けな第1レベルの依存関係のアップグレードには影響しません。
ロス・アレン

回答:


423

更新3:他の回答でも指摘されているように、このnpm ciコマンドは、CIコンテキストで高速かつ再現可能なビルドを実現する追加の方法としてnpm 5.7.0で導入されました。詳細については、ドキュメントnpmブログを参照してください。


更新2:ドキュメントを更新および明確化するための問題は、GitHubの問題#18103です。


更新1:以下で説明されている動作がnpm 5.4.2で修正されました。現在意図されている動作は、GitHubの問題#17979で概説されています


元の回答:問題#16866で説明されているようにpackage-lock.jsonnpm 5.1.0での動作が変更されました。観察される動作は、バージョン5.1.0の時点でnpmによって意図されているようです。

つまり、で依存関係の新しいバージョンが見つかった場合は常にpackage.jsonオーバーライドできます。依存関係を効果的に固定するには、プレフィックスなしでバージョンを指定する必要があります。たとえば、またはの代わりにバージョンを記述する必要があります。次に、との組み合わせにより、再現可能なビルドが生成されます。明確にするために:単独ではルートレベルの依存関係がロックされなくなりました!package-lock.jsonpackage.json1.2.0~1.2.0^1.2.0package.jsonpackage-lock.jsonpackage-lock.json

この設計上の決定が良かったかどうかは議論の余地がありますが、問題#17979の GitHubでこの混乱の結果として進行中の議論があります。(私の目では、それは疑わしい決定です;少なくとも名前lockはもはや真実ではありません。)

もう1つの注意事項:npmjs.orgではなくGitHubから直接パッケージをプルする場合など、不変のパッケージをサポートしないレジストリーにも制限があります。詳細については、このパッケージロックのドキュメントを参照してください。


43
その時のハックは何npm updateですか?:私は同じ気持ちことを持っていたoをnpm install更新DEPSを、私はそれを信じたくはありません..しかし、それは悲しいこと本当だように思える...とにかく使用するオプションまだあるnpm shrinkwrapロックDEPSには、間違いなく名パッケージロックが正しくありませんそれは...フリーズ、またロックの依存関係はありませんとして
Jurosh

266
なんてめちゃくちゃ!世界最大のパッケージマネージャーですが、どのように機能するかについてのドキュメントはありません。誰もがそれが何をすべきかについて推測しており、それは意見の戦争に変わります。議論は良いですが、実際にリリースされる前に行われるべきです。ある時点で、誰かが最後の呼び出しを行う必要があり、その後、実装、文書化、リリースされます。PHPは委員会によって設計され、アドホックにまとめられ、それがどのようになっているかを調べています。この重要で広く使用されているツールに同じことが起こるのを見たくありません。
Landon Poch 2017

85
では、package-lockを使用する意味は何ですか?異なるワークスペースに同じ環境を作成すると思いましたが、何も実行されていないことが
わかりました

17
「その後、package.jsonとpackage-lock.jsonを組み合わせると、再現可能なビルドが生成されます。」「package-lock.json」にはどのような役割がありますか?バージョン接頭辞が使用されていない場合、「package.json」だけではすでに再現可能なビルドが生成されませんか?
ジャニスElmeris

12
@JānisElmerispackage.jsonでは深い依存関係をロックダウンできないと思います...
Juan Mendes

165

私は、NPMの新バージョンが存在することを発見しました5.7.1の新しいコマンドを使用してnpm ciからインストールします、package-lock.jsonのみ

新しいnpm ciコマンドは、ロックファイルからのみインストールします。package.jsonとロックファイルが同期していない場合、エラーが報告されます。

これは、node_modulesを破棄し、最初から再作成することで機能します。

あなたがあなたのロックファイルにあるものだけを取得することを保証するだけでなく、node_modulesで始めないときは、npm installよりもはるかに高速です(2x-10x!)。

名前からわかるように、継続的な統合環境にとって大きな恩恵となることを期待しています。また、Gitタグから本番環境にデプロイするユーザーには、大きな利益が期待できます。


133
これは、ロックファイルが存在する場合のデフォルトの動作です。
nullability

13
それで、彼らは私がnpmをどのように動作させるかを変更しました、それを数ヶ月後にnpm ciとして戻すだけですか?
スコットフラック

1
私はまだ混乱しています。ドキュメントでは、そのプロジェクトでコマンドを実行する前に、パッケージロックと最新のインストールがあることを確認してください:npm installnpm ciとあります。npm installpackage-lock.jsonファイルを上書きしませんか?
adiga

1
AFAIK:@adiga-バージョン5.4以降、packages.jsonの仕様を満たすために、必要な場合にnpm のみロックファイルを変更します。したがって、パッケージがと言っthatpackage: 1てロックが言った..: 1.0.4場合、開発者は編集して言うことができますthatpackage: 2-と1.0.4は、新しく指定された範囲と互換性がないため、ロックファイルを強制的に変更します。変更しない場合packages.json、ロックファイルを削除するまで、正確なバージョンでロックされたままになります。[ロックされないままで、packages.jsonを変更しなかった場合は、バグレポートを提出してください。]
ToolmakerSteve '30

1
@George私が読んだ情報(最近のバージョンのnpm用)と私の限られたテストから:はい、両方とも。
Venryx

95

新しく導入された

npm ci

npm ciは、大規模なチームに最大のメリットを約束します。パッケージロックに「サインオフ」する機能を開発者に与えることで、大規模なチーム全体でのより効率的なコラボレーションが促進され、ロックファイルにあるものを正確にインストールできる機能により、月に数百時間ではないにしても数十時間の開発者を節約でき、チームを解放できます。素晴らしいものを作り、出荷するためにより多くの時間を費やすため。

npm ciより高速で信頼性の高いビルドのための紹介


3
これは私には正しいようです?他の誰かが確認できますか?
phouse512 2018年

6
@ phouse512これは正しいです。私たちはほとんどのみを使用しnpm cinpm install新しいパッケージを更新またはインストールする場合にのみ使用します。
Jacob Sievers

1
最近のコメントなどこれが私の答えです。彼らがひどいスナフを修正できないのは残念ですが、新しいゴスペルが「npm ci」である場合は問題ありません。適応できます。
Svend

残念それは常に既存の削除node_modulesそうでなければ、空が、重要なシンボリックリンクの場合でも、ディレクトリをローカルに再構築します。:(
ジョーAtzberger

2
@ToolmakerSteve息を止めないで!ディレクトリの内容を削除することは、単にディレクトリを削除することよりもかなり遅いと思います。内容を列挙してから、O / Sに対して1つの削除コマンドではなく、一連の削除コマンドを発行する必要があります。以前はnpmで平準化されていたパフォーマンスの問題とそれを使用した改善によりnpm ci、かなり一般的でないユースケースのパフォーマンスを低下させる可能性があるものを導入することは非常に消極的だと思います。ディスクの使用量を減らすためにハードリンクを利用していますが、pnpm.js.orgをチェックアウトすることもできます。
Caltor、

64

簡潔な答え:

  • npm install package.jsonの要件を満たしている場合にのみ、package-lock.jsonを受け入れます。
  • これらの要件を満たさない場合、パッケージが更新され、package-lockが上書きされます。
  • ビルドに失敗した場合は、パッケージロックが発生したときに書き換えるのではなく、を使用してくださいnpm ci

これは説明する可能性のあるシナリオです(NPM 6.3.0で検証済み)

次のように、package.jsonで依存関係を宣言します。

"depA": "^1.0.0"

次に、次のようにしnpm installてpackage-lock.jsonを生成します。

"depA": "1.0.0"

数日後、 "depA"の新しいマイナーバージョンがリリースされます( "1.1.0"など)。次のことが当てはまります。

npm ci       # respects only package-lock.json and installs 1.0.0

npm install  # also, respects the package-lock version and keeps 1.0.0 installed 
             # (i.e. when package-lock.json exists, it overrules package.json)

次に、package.jsonを手動で次のように更新します。

"depA": "^1.1.0"

次に、再実行します。

npm ci      # will try to honor package-lock which says 1.0.0
            # but that does not satisfy package.json requirement of "^1.1.0" 
            # so it would throw an error 

npm install # installs "1.1.0" (as required by the updated package.json)
            # also rewrites package-lock.json version to "1.1.0"
            # (i.e. when package.json is modified, it overrules the package-lock.json)

4
これは確かに「ロック」ファイルの意図された動作です。どうやら、それは古いバージョンのNPMには当てはまりませんでした。
Blockost、2019年

1
次に、npmはどのようにしてpackage.jsonへの最後の更新を追跡しますか?package.jsonとpackage-lock.jsonを別のコンピューターに移動するとどうなりますか?新しいコンピューターのnpmは、package.lockが元のパッケージであるか、それが更新されているかをどのようにして確認し、package-lock.jsonを更新する必要があるかどうかを判断しますか?
Lahiru Chandima

3
@LahiruChandima更新は実際には追跡されません。npm installは、package.jsonをインストールし、それに応じてpackage-lock.jsonを再構築する条件をpackage-lock.json満たさない限り、ロックされたバージョンを使用package.jsonします。package.json既存のパッケージロックが更新されpackage.jsonた条件を満たすように変更した場合、それは引き続き使用されますpackage-lock
Ahmad Abdelghany

1
package.jsonの要件を満たすモジュールがnode_modulesにすでにある場合npm install、package-lock.jsonに関係なく、何もしません。package.jsonで指定されたサーバーと一致する利用可能な更新がある場合でも、パッケージを明示的に更新する必要があります。少なくともそれは私の長年の経験です。
carlin.scott

1
@ToolmakerSteve私は@ carlin.scottが報告した動作にも懐疑的でしたが、私はそれをテストしただけで、実際には彼は正しいです。内のバージョンnode_modulesがの範囲を満たし、ファイルpackage.jsonがないpackage-lock.json場合、npmは実行時にモジュールを更新しませんnpm installnpm update(またはnpm-check最新の)を使用して依存関係を更新できるので問題ないと思います。この動作は、誰かがに1つのエントリを追加するだけでpackage.json、関係のないパッケージがsem-verを満たす最新のものに更新されたくない場合に速くなります。範囲。
Venryx

19

npm ci代わりにコマンドを使用しnpm installます。

「ci」は「継続的統合」の略です。

寛大なpackage.jsonファイルの依存関係ではなく、package-lock.jsonファイルに基づいてプロジェクトの依存関係をインストールします。

それはあなたのチームメイトと同一のビルドを生成し、それもはるかに高速です。

詳細については、次のブログ投稿をご覧ください。https//blog.npmjs.org/post/171556855892/introducing-npm-ci-for-faster-more-reliable


2
ciコマンドを発表Docsやブログ記事で述べたように、「継続的インテグレーション」を参照:blog.npmjs.org/post/171556855892/...
ジョーAtzberger

ジョーありがとう。回答を正しい名前で更新し、ブログ投稿にリンクしました。😊(これを読んでいる人のために、以前は「クリーンインストール」の略だと言っていました)
Daniel Tonon

「また、はるかに高速です」- node_modulesフォルダを削除し、最初から再作成します。本当に速いですか?いnpm install、削除node_modulesフォルダには、あまりにも、?
izogfif

速度はnpmがダウンロードするパッケージを計算する必要がないためだと思います。npm install実行時にすべてのパッケージの依存関係を解決する必要があると考えてください。npm ci「これらの正確なモジュールを入手する」の単なる買い物リストです。
Daniel Tonon

8

将来的には、あなたが使用することができます--from-lock-fileインストールする(または類似の)フラグのみからpackage-lock.json、それを修正することなく。

これは、再現可能なビルドが重要なCIなどの環境で役立ちます。

機能の追跡については、https://github.com/npm/npm/issues/18286を参照してください


疑わしい。オペレーティングシステムごとに依存関係が異なる場合、どうすれば機能しないものを強制インストールできますか?
Yevgeniy Afanasyev

4
@YevgeniyAfanasyevそのフラグの代わりに、npm ciあなたの質問を処理するものとして実装されました。
spex 2018年

8

この問題はnpm v5.4.2で修正されたようです

https://github.com/npm/npm/issues/17979

(スレッドの最後のコメントまでスクロールします)

更新

5.6.0で実際に修正されました。5.4.2にクロスプラットフォームのバグがあり、それが原因で問題が引き続き発生していました。

https://github.com/npm/npm/issues/18712

アップデート2

ここで私の答えを参照してください:https : //stackoverflow.com/a/53680257/1611058

npm ci 既存のプロジェクトを今すぐインストールするときに使用する必要があるコマンドです。


5
5.4.2を使用していても、package-lock.jsonが変更されnpm iます。たとえば、サポートしていないマシンでモジュールfseventsを削除するとモジュールが削除され、npm iサポートしているマシンでfseventsモジュールを再度追加するとモジュールが再度追加されnpm iます。
hrdwdmrbl 2017年

次に、これを説明するnpm GitHubリポジトリで新しい問題を提起する必要があります。それが機能すると想定されている方法で機能しない場合、緊急に修正する必要がある優先度の高いバグと見なします。
Daniel Tonon

私は同じ見ている@hrdwdmrbl fsevents私の低下package-lock.jsonとをnpm@5.5マックOS Xの貢献者と協力しながら。あなたが問題を開いていない場合、私はします。
AL、X X

@hrdwdmrblコメントを残し、SOに戻ってコメントを更新するのを忘れた後、それ(および関連する問題の長いスレッド)を見つけました。お返事ありがとうございます。すべて順調。
AL X

4

あなたはおそらく次のようなものを持っています:

"typescript":"~2.1.6"

あなたにpackage.jsonそのあなたのケースであることに、最新のマイナーバージョンへの更新をNPM2.4.1

編集:OPからの質問

しかし、「npm install」がロックファイルを変更する理由は説明されていません。ロックファイルは再現可能なビルドを作成するためのものではありませんか?その場合、semverの値に関係なく、同じ2.1.6バージョンを使用する必要があります。

回答:

これは、完全な依存関係ツリーをロックすることを目的としています。まあ言ってみればtypescript v2.4.1必要ですwidget ~v1.0.0。npmをインストールすると、インストールされますwidget v1.0.0。後で仲間の開発者(またはCIビルド)がnpmインストールを実行して取得しますtypescript v2.4.1が、widgetに更新されましたwidget v1.0.1。これで、ノードモジュールが同期しなくなりました。これがpackage-lock.json妨げるものです。

またはより一般的には:

例として、

パッケージA:

{"名前": "A"、 "バージョン": "0.1.0"、 "依存関係":{"B": "<0.1.0"}}

パッケージB:

{"名前": "B"、 "バージョン": "0.0.1"、 "依存関係":{"C": "<0.1.0"}}

そしてパッケージC:

{「名前」:「C」、「バージョン」:「0.0.1」}

これらがレジストリで使用可能なA、B、およびCの唯一のバージョンである場合、通常のnpmインストールAがインストールされます。

A@0.1.0-B@0.0.1-C@0.0.1

ただし、B @ 0.0.2が公開されている場合は、新しいnpmインストールAがインストールされます。

A@0.1.0-B@0.0.2-C@0.0.1は、新しいバージョンがBの依存関係を変更しなかったと想定しています。もちろん、新しいバージョンのBには、新しいバージョンのCと任意の数の新しい依存関係を含めることができます。そのような変更が望ましくない場合、Aの作成者はB@0.0.1への依存関係を指定できます。ただし、Aの作成者とBの作成者が同じ人物ではない場合、Aの作成者は、Bがまったく変更されていない場合に、新しく公開されたバージョンのCを取り入れたくないと言うことはできません。


OP質問2:では、私が正しく理解しているかどうかを確認しましょう。あなたが言っているのは、ロックファイルが二次依存関係のバージョンを指定しているにもかかわらず、package.jsonのあいまい一致に依存して、トップレベルの依存関係を決定しているということです。それは正確ですか?

回答:いいえ。package-lockは、で説明されているルートパッケージを含むパッケージツリー全体をロックしますpackage.json。場合typescriptにロックされている2.4.1あなたにpackage-lock.jsonそれが変更されるまで、それはそのように残っている必要があります。そして明日typescriptリリース版としましょう2.4.2。私がブランチをチェックアウトして実行するとnpm install、npmはロックファイルを尊重してインストールし2.4.1ます。

詳細package-lock.json

package-lock.jsonは、npmがnode_modulesツリーまたはpackage.jsonを変更する操作に対して自動的に生成されます。中間の依存関係の更新に関係なく、後続のインストールで同一のツリーを生成できるように、生成された正確なツリーについて説明します。

このファイルは、ソースリポジトリにコミットすることを目的としており、さまざまな目的で使用されます。

チームメイト、デプロイメント、継続的インテグレーションがまったく同じ依存関係を確実にインストールできるように、依存関係ツリーの単一の表現を説明します。

ユーザーがディレクトリ自体をコミットする必要なく、node_modulesの以前の状態に「タイムトラベル」する機能を提供します。

読みやすいソース管理の差分を使用して、ツリーの変更の可視性を高める。

また、npmが以前にインストールされたパッケージのメタデータ解決の繰り返しをスキップできるようにすることで、インストールプロセスを最適化します。

https://docs.npmjs.com/files/package-lock.json


29
しかし、「npm install」がロックファイルを変更する理由は説明されていません。ロックファイルは再現可能なビルドを作成するためのものではありませんか?その場合、semverの値に関係なく、同じ2.1.6バージョンを使用する必要があります。
Viperベイリー

3
それが私が言っていることです。パッケージロックファイルにはtypescript@2.1.6と記載されていますが、npm installを実行すると、エントリがtypescript@2.4.1に置き換えられます。
Viperベイリー

5
私はこれと同じ問題を経験しました。CI / CDでは、package-lock.jsonがプルダウンされて実行されますnpm installが、package-lock.jsonファイルが変更されているため、次の変更をプルする前にリセットを実行する必要があります。
BayssMekanique 2017

15
わかりません。後続のインストールで引き続きアップグレードが行われる可能性がある場合、これは「ロック」ファイルですか?
ロス・アレン

5
私は彼らがこのファイルを「info」と「lock」として持つという考えから始めたと思います、そして、それが「info」ファイルだけであることに決めました。より適切な名前は「package-info.json」です。「package-lock.json」からインストールし、「package.json」を無視する「npm install -lock」を用意したい
Jeremy

2

おそらくあなたはこのようなものを使うべきです

npm ci

使用する代わりに npm install パッケージのバージョンを変更したくない場合する。

公式ドキュメントによると、npm installnpm ciプロジェクトに必要な依存関係をインストールします。

主な違いは、リファレンスとしてnpm installパッケージをインストールすることpackge.jsonです。の場合、参照としてnpm ciパッケージをインストールしpackage-lock.json、正確なパッケージがインストールされるたびに確認します。


1

彼らのgithubページにこれに関する未解決の問題があります:https//github.com/npm/npm/issues/18712

この問題は、開発者が異なるオペレーティングシステムを使用している場合に最も深刻です。


パッケージロックで書き換えが意図されている、問題はこの結果ではありません
Z. Khullah

0

編集:「ロック」という名前はトリッキーなもので、そのNPMはヤーンに追いつけようとします。ロックされたファイルではありません。package.jsonユーザーが修正したファイルで、「インストール」するとnode_modulesフォルダツリーが生成され、そのツリーがに書き込まれpackage-lock.jsonます。つまり、その逆です-依存関係バージョンはpackage.jsonいつものようにプルされ、package-lock.json呼び出される必要がありますpackage-tree.json

(非常に多くの反対投票の後、これにより私の答えがより明確になったことを願っています)


単純な答え:package.json通常どおり依存関係を保持しますが、これpackage-lock.jsonは「正確で、より重要なことには再現可能なnode_modulesツリー」です(npm docs自体から取得)。

トリッキーな名前について言えば、そのNPMはYarnに追いつけようとしています。


1
npm installを実行すると、package-lockが更新されるためです。
Jean-Baptiste
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.