元の package.json
変更後の package.json

package.json Diff: npm マニフェストをオンラインで比較

古い package.json を左に、新しいものを右に貼り付けると、どの dependencies、scripts、engines が変わったかを正確に確認できます。ブラウザ内で動作し、何もアップロードされません。

この package.json diff ツールについて

2 つの npm package.json ファイルを並べて比較するための、ブラウザ内で動く無料ツールです。古いマニフェストを左、新しいものを右に貼り付けると、差分が文字単位でハイライトされます。テキストはマシンから出ないので、マニフェストがプライベートリポジトリや未リリース製品のものである場合に重要です。

Renovate や Dependabot の PR が来て、バージョン bump 以外に何が実際に変わったかを知る必要がある瞬間のために作られています。誰かが script の編集を紛れ込ませていないか? engines フィールドが Node 18 から Node 20 に動いていないか? peerDependency が厳しくなっていないか? GitHub の diff ビューはこれの一部に答えますが、複数の PR を続けて見たり、まだ push されていないブランチを比較したりするときは、2 つのマニフェストをきれいな 2 ペインビューに貼り付けるほうが速いです。

内部では、これは compare-json ページを動かしているのと同じ JSON 対応 diff で、npm と yarn のワークフロー向けに枠組みと文言を調整したものです。両方のマニフェストは diff を実行する前に JSON としてパースされ整形されるので、見た目だけの空白の違いがハイライトを汚しません。JSON 以外のマニフェスト形式の生テキスト diff が必要なら、compare-text がそれをカバーし、compare-yaml が pnpm-lock.yaml を扱います。

diff の実際の動作

各ペインは JSON としてパースされます。パースが成功すると、マニフェストは一貫した 2 スペースインデントで再整形され、キーの順序は書かれたまま保たれます。パースに失敗した場合 (はぐれカンマ、欠けた波括弧、文字数が足りないコピペなど) ツールはプレーンテキストモードにフォールバックし、どの行で壊れたかを教えます。両側が有効な JSON になると、diff は文字単位で実行され、その後セマンティッククリーンアップが変更を読みやすい塊に再グループ化するので、^18.2.0 から ^19.0.0 へのバージョン bump は 9 個の文字編集ではなく 1 つの編集として読めます。

右ペインの挿入は緑、左ペインの削除は赤で表示されます。2 つのペインはスクロールロックされているので、片側で devDependencies の奥深くに変更を見つけたとき、もう一方も同じキーにジャンプします。整形後はテキストレベルの diff なので、構造的な変更を人間が読むように見ます: 削除された依存は行として消え、変更された semver 範囲は値の中でハイライトされ、新しい script は配置した位置の scripts ブロックに収まります。

ツールが意図的にしないこと: これは依存リゾルバではありません。caret 範囲の bump がどの推移的パッケージを引き込むか、peer が満たされているか、新しいバージョンがセキュリティ勧告を含むかは教えません。それにはローカルで npm install に続いて npm audit を実行するか、npm を Snyk や GitHub の Dependabot アラートのような lockfile を理解するサービスとともに使ってください。このページはマニフェストのテキストが何を言っているかを教えます。解決の作業はパッケージマネージャの仕事です。

3 ステップで package.json を diff する方法

2 つのテキストペイン、1 つの diff。CLI フラグなし、インストール手順なし、読むべきパッチ形式なし。

  1. 1

    古いマニフェストを左に貼り付ける

    package.json の以前のバージョンを、エディタから、git show main:package.json から、またはチームメイトからコピーします。左ペインに貼り付けます。ツールはそれを JSON としてパースし整形します。JSON が無効なら、エディタはパースエラーを表示するので、diff する前にスニペットを修正できます。

  2. 2

    新しいマニフェストを右に貼り付ける

    更新されたバージョンで同じことをします。Renovate や Dependabot の PR を見ているなら、最も簡単なソースは PR ブランチからの生ファイルです。両方のファイルは一貫したインデントで整形されるので、見た目だけの空白編集は diff に偽の変更として現れません。

  3. 3

    ハイライトされた差分を読む

    削除は左に赤い取り消し線として、挿入は右に緑として表示されます。まず依存ブロックをスキャンし、次にコマンド編集のために scripts セクションを確認し、それから engines と peerDependencies フィールドを見ます。単一の値内のバージョン bump は変更された文字をハイライトするので、パッチ bump とメジャー bump を一目で区別できます。

package.json diff が正しい選択になるとき

Renovate や Dependabot の PR をレビューする

ボットが朝に 15 個の PR を開きます。ほとんどはルーチンですが、1 つに script の変更、または絞られた peerDependency、または CI イメージを壊す engines の bump が紛れ込んでいます。PR タイトルには "chore(deps): bump foo from 4.1.0 to 4.2.1" とあり、自動操縦で信頼してしまいます。前後の package.json を diff に貼り付ければ、5 秒で他に何も動いていないことを確認できます。これは JS エンジニアがマニフェスト diff に手を伸ばす最も一般的な理由です。

マージ前に 2 つのブランチを比較する

あなたと同僚が別々のフィーチャーブランチで package.json を触りました。編集が異なるブロックにあるので Git はクリーンにマージしますが、クリーンなマージは正しいマージを意味しません。両ブランチのマニフェストを diff に貼り付けて、片方のブランチが落とした script、片方のブランチがダウングレードした依存、または両方のブランチが異なるバージョンで同じパッケージを追加した衝突を見つけます。マージ結果に対して CI が npm ci を実行した後に発見するより安上がりです。

npm install が package-lock.json に昇格させたものを監査する

package.json を編集するのは変更の半分です。残り半分は package-lock.json が解決済みツリーについて記録するものです。npm install を実行した後、古い lockfile を新しい lockfile の隣に貼り付けて、どの推移的パッケージが一緒に来たかを見ます。caret 範囲が深くネストされた依存の新しい minor を引き込んだとき、驚きの追加はよくあります。生の lockfile 検査には compare-json ページのほうが大きなファイルを扱いやすいです。このページはマニフェスト自体に最適です。

リグレッション後のダウングレードをチェックする

リリースが出て、バグが現れ、bisect し、容疑者は依存ツリーのどこかにいます。最後に良かったリリースの package.json を現在のものの隣に貼り付けます。変更のないブロックは頭の中で切り捨てて、ハイライトされたバージョン範囲に集中します。修正はしばしば、最後の green ビルドで pin されていたバージョンへの 1 つのライブラリのダウングレードです。容疑者を見つけたら、上流の問題が解決するまで、正確なバージョン (caret なし、tilde なし) でロックします。

ローカルマニフェストをチームメイトのものと比較する

2 人のエンジニア、1 つの厄介なマージ、リベースの最後に 2 つの異なる package.json ファイル。lockfile はさらに混乱しています。両方のマニフェストを並べて貼り付けて、どのキーが食い違うかを見て、git merge -X theirs の結果を読まずに受け入れるのではなく意図的に解決します。これは、npm install があなたのものと違うツリーを取り、マニフェストの drift が疑われる新しいコントリビューターをオンボーディングするときの正しいツールでもあります。

ライブラリの package.json の publish 前レビュー

ライブラリで npm publish を実行する前は、重要なマニフェストフィールドはアプリのものとは異なります: mainmoduletypesexportsfilespeerDependenciesengines。publish しようとしているマニフェストを最後に publish したものと diff します。落とされた peerDependencies エントリ、変更された exports 条件、絞られた engines 範囲は、npm 自体が警告しない方法で消費者を壊しえます。Node.js packages docs がこれらのフィールドの意味のリファレンスです。

知っておく価値のある package.json フィールド

実際の package.json diff に出てくるフィールドとその意味。Renovate PR を承認する前や、両方がマニフェストに触れた 2 つのブランチをマージする前にスキャンする価値があります。

TopicWhat this tool does
dependencies vs devDependencies vs peerDependenciesdependencies はパッケージとともに出荷され、それを消費する誰でもインストールします。devDependencies はプロジェクトルートで npm install を実行したときだけインストールされ、下流の消費者には決してインストールされません。peerDependencies はライブラリがホストに提供することを期待するパッケージ (典型的には React、テストフレームワーク、バンドラ) で、npm 7+ は競合がない限り自動的にインストールします。これらのブロック間でパッケージを移動すると、誰がインストールコストを払うかが変わります。
caret (^) と tilde (~) semver 範囲caret ^1.2.32.0.0 を含まない任意のバージョンを許可します。これは npm のデフォルトで最も緩い一般的な範囲です。tilde ~1.2.31.3.0 を含まないパッチだけを許可します。1.2.x は tilde と同じです。* は任意のバージョンを意味します (本番では使わないでください)。latest はインストール時に解決され、再現不可能なビルドを生むので避けてください。
正確な pin (範囲プレフィックスなし)caret も tilde もなく "react": "18.2.0" と書くと、その正確なバージョンに pin されます。lockfile と組み合わせると、セキュリティパッチを自動的に受け取らないコストで最も再現可能なインストールが得られます。すべてを pin するチームもあれば、caret プラス lockfile の組み合わせに頼るチームもあります。普遍的に正しい答えはありませんが、トレードオフはより決定論的なビルドかより古い依存かです。
package-lock.json の決定性package-lock.json は推移的を含む依存ツリーのすべてのパッケージの正確な解決済みバージョンを記録します。npm ci は lockfile からインストールし変更を拒否します。npm install は範囲がより新しいバージョンを許可すれば更新する可能性があります。CI では常に npm ci を使ってください。開発者には、結果として生じる lockfile の変更をコミットする限り npm install で問題ありません。
monorepo 用の workspaces フィールドworkspaces 配列は、モノレポ内の兄弟ディレクトリをリンクされたパッケージとして扱うよう npm に伝えます。ルートでの npm install はすべての workspaces をインストールし、単一の hoist された node_modules ツリーを作成します。Yarn と pnpm は独自の慣例で workspaces をサポートし、特に pnpm はあまり積極的に hoist しないので、インストール時により多くの依存リークバグを捕まえます。
engines フィールドengines.node はパッケージがサポートする Node.js バージョンを宣言します。デフォルトでは npm はホストがこれに違反したときに警告するだけです。.npmrcengine-strict=true でハードエラーになります。engines フィールドを bump することは古い Node に固定された消費者にとって破壊的変更で、Renovate の "chore" PR の中に隠れる種類の変更です。常に engines diff を読んでください。
ES modules 用の exports フィールドexports フィールドは、消費者がパッケージからインポートできるパスと、どの条件 (importrequiretypesnodebrowser) がどのファイルに解決されるかを制御します。エントリの追加または削除は下流コードへの破壊的変更です。Node.js packages documentation が解決ルールを詳細にカバーします。意図的に新しいエントリポイントを追加していない限り、exports diff はメジャーバージョン相当の編集として扱ってください。
package.json 内のファイル順序package.json のトップレベルキーには強制された順序はありません。慣例として、ほとんどのプロジェクトは nameversiondescription で始まり、次に scripts、それから依存です。依存ブロック内では、キーによるアルファベット順が事実上の標準で、ほとんどのパッケージマネージャは保存時にブロックをソートします。並び替わったが他は同一のエントリを示す diff は通常、ツールの違いであり実際の変更ではありません。

package.json diff: よくある質問

これは npm diff や npm-check-updates とどう違いますか?

npm diff は、tarball とソースを含む、registry 上のパッケージの 2 つの公開バージョンを比較する組み込み npm コマンドです。npm-check-updates (ncu) は、マニフェストのどの依存により新しいバージョンが利用可能かを報告します。どちらも、ディスク上または 2 つのブランチにある任意の 2 つの package.json ファイルの差分を見せません。このツールはそれをします。アップグレードすべきものを知るには ncu を、リリース間の registry 側の変更を見るには npm diff を、自分の前後のマニフェストを並べてビューで読むにはこのページを使ってください。

セキュリティの監査や既知の脆弱性のチェックをしますか?

いいえ。このページはテキストの diff だけです。npm registry、GitHub Advisory Database、その他の脆弱性サービスに問い合わせません。セキュリティ監査には、インストール済みツリーに対して npm audit を実行し、パッケージの来歴を確認するために npm audit signatures を使うか、Snyk、Socket、Dependabot アラートに頼ってください。このツールはマニフェストで何が変わったかを知りたいときの正しい選択です。変更を出荷して安全かどうかを知りたいときは間違った選択です。

推移的依存の変更を検出しますか?

マニフェスト単独からは検出しません。package.json は直接の依存と要求された範囲だけをリストします。推移的を含む完全な解決済みツリーは package-lock.json (または yarn.lockpnpm-lock.yaml) にあります。解決済みツリーを比較するには、両方の lockfile を diff に貼り付けます。lockfile は大きいので、compare-json ページのほうがこのページより上手く扱います。pnpm-lock.yaml には特に compare-yaml を使ってください。このページはマニフェストに最適化されています。

2 つの package-lock.json ファイルをどう比較しますか?

マニフェストと同じように両方の lockfile をペインに貼り付けます。ツールはそれらを JSON としてパースし、整形し、diff します。lockfile は何千行にも達することがあるので、ハイライトされた diff は長くなることがあります。まずトップレベルの packages エントリ、次に version フィールドに集中してください。およそ 5000 行を超えるファイルには、同じエンジンで大きな JSON ペイロードを扱うようにセットアップされた compare-json ページのほうが適しています。

caret (^) と tilde (~) 範囲の違いは何ですか?

両方ともマニフェストを手動で編集することなく更新を許可する semver 範囲です。caret ^1.2.3 は左端の非ゼロ桁を変えない任意のバージョンを許可するので、1.2.3 から 1.999.999 まで受け入れられますが、2.0.0 は受け入れられません。tilde ~1.2.3 はより厳格で、パッチ更新だけを許可するので、1.2.3 から 1.2.999 まで受け入れられますが 1.3.0 は受け入れられません。caret は npm のデフォルトでより緩い範囲、tilde はライブラリに minor リリースで壊した履歴があるときに手を伸ばすものです。

大きな lockfile にサイズ制限はありますか?

実質的にはあります。diff はブラウザで動くので、非常に大きな入力 (例えばモノレポからの 20,000 行の lockfile) はメモリ次第でページを遅くしたりタブを止めたりすることがあります。一般的なアプリのマニフェストと片側数千行までの lockfile では、diff は事実上瞬時に完了します。それより大きなファイルには、compare-json ページのほうが良い入口です。巨大な lockfile を定期的に比較するなら、ローカルで git diff package-lock.json を実行してページャーにパイプすることを検討してください。そのワークフローはどのブラウザツールよりもさらにスケールします。

プライバシーと動作の仕組み

マニフェストはブラウザを離れません。diff、JSON のパース、ハイライト、レンダリングはすべてあなたのマシンで動作します。テキストをアップロードしたり、ログに残したり、サードパーティのサービスに渡したりしません。これは独自コードで特に重要です: 未リリースのライブラリの package.json やプライベートリポジトリの lockfile をクラウドサービスに貼り付けること自体が、特にマニフェストが社内 scoped パッケージ、プライベート registry ホスト、開発中の製品名を名指している場合、雇用主のデータ取り扱いポリシーに違反する可能性があります。主張の検証は簡単です。ブラウザの DevTools を開き、Network タブに切り替え、両方のマニフェストを貼り付けて見守ります。比較するときに送信リクエストはありません。同じプライバシーモデルは、compare-json、pnpm-lock.yaml 用の compare-yaml、一般的なコードレビュー用の git-diff-online など、他のツール全体に渡って成り立ちます。基礎となる仕様については、Yarn の設定リファレンス と npm の package.json ドキュメント を参照してください。