セマンティックバージョニングと package.json のバージョン指定 - ^ と ~ の違い、0.x の罠

セマンティックバージョニングと package.json のバージョン指定 - ^ と ~ の違い、0.x の罠

作成日:
読了:8
更新日:
この記事を読む人におすすめPR / Amazonアソシエイト

当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。

package.json"react": "^18.2.0"^、なんとなく付けていませんか。この記号ひとつで「次の npm install でどのバージョンまで上がるか」が変わります。この記事では、セマンティックバージョニング(semver)と npm のバージョン指定を、semver.org・npm 公式・node-semver を一次ソースに整理します。

セマンティックバージョニングとは

バージョンは MAJOR.MINOR.PATCH の3つの数値。上げる基準は仕様で決まっています。

いつ上げるか
MAJOR後方互換性を壊す API 変更をしたとき
MINOR後方互換を保ったまま機能追加したとき
PATCH後方互換のあるバグ修正をしたとき

上位を上げたら下位はゼロに戻します(MINOR を上げたら PATCH は 0)。1.0.0 で「公開 API を定義する」とされ、以降この公開 API の変化に応じて番号を動かします。

0.y.z(初期開発版)の特別扱い

仕様には「メジャー0(0.y.z)は初期開発用で、いつ何が変わってもよい。公開 API は安定とみなすべきでない」と明記されています。この特例が、後述する ^ の挙動にも効いてきます。

プレリリースとビルドメタデータ

  • プレリリース版: 1.0.0-alpha1.0.0-rc.1 のようにハイフンで付ける。通常版より優先順位は低い1.0.0-alpha1.0.0 より前)
  • ビルドメタデータ: 1.0.0+20130313 のようにプラスで付ける。優先順位の比較では無視される

優先順位の例(仕様より): 1.0.0-alpha1.0.0-alpha.11.0.0-beta1.0.0-rc.11.0.0

キャレット ^ とチルダ ~

ここが本題です。npm の範囲指定で最頻出の2つを比べます(範囲の厳密な定義元は node-semver)。

指定許可される範囲上がる桁
^1.2.3>=1.2.3 かつ <2.0.0MINOR・PATCH
~1.2.3>=1.2.3 かつ <1.3.0PATCH のみ
  • ^(キャレット): 「いちばん左の0でない桁」を固定し、それ未満を更新。^1.2.3 なら MINOR と PATCH が上がる
  • ~(チルダ): MAJOR.MINOR.PATCH が揃っていれば PATCH のみ更新

つまり通常は ^ のほうが広く(MINOR まで)、~ のほうが狭い(PATCH のみ)

0.x の罠: ^ が ~ に縮退する

初学者が必ずハマるのがこれです。0.x では ^ の挙動が変わります(前述の「メジャー0は不安定」が反映されるため)。

指定許可される範囲実質
^0.2.3>=0.2.3 かつ <0.3.0PATCH のみ~0.2.3 と同じ!)
~0.2.3>=0.2.3 かつ <0.3.0PATCH のみ
^0.0.3>=0.0.3 かつ <0.0.4更新なし(実質固定)

^1.x は MINOR まで上げるのに、^0.2.3 は MINOR を上げません。「メジャー0の MINOR 更新は破壊的変更でありうる」という semver の考えに沿った挙動です。依存が 0.x のうちは ^ でも MINOR は上がらない——これを知らないと「なぜ更新されない/されすぎる」で混乱します。

その他の範囲指定

  • x / *: 1.2.x>=1.2.0 かつ <1.3.0* は任意
  • ハイフン範囲: 1.2.3 - 2.3.4 は両端を含む(>=1.2.3 かつ <=2.3.4
  • OR: ^2 || ^3 || ^4 でいずれかを満たせば OK
  • 完全一致: 4.18.2 のように記号なしで固定

NOTE

範囲指定はデフォルトでプレリリース版を除外します(^1.2.32.0.0-rc.1 を含まない)。プレリリースを拾うには範囲側にもプレリリースタグを書く必要があります。

package.json と package-lock.json

範囲指定だけでは「いつ誰がインストールしても同じバージョン」は保証されません。そこを担うのが package-lock.json です。

  • package.json: 範囲^1.2.3 等)を書く=「これくらいの幅で許す」という意思表示
  • package-lock.json: 実際に入った正確なバージョンを記録=「次回も同一ツリーを再現」する。ソース管理にコミットするのが公式の想定

この2層構造で「柔軟な範囲指定」と「再現性」を両立します。

npm install / ci / update の違い

コマンド挙動
npm install範囲を満たす形で解決し、node_modules と lock を生成・更新(lock を書き換えうる)
npm cilock 必須・lock に厳密追従。lock と package.json が不整合ならエラーで停止し、書き換えない(CI 向け・決定的)
npm updatesemver の範囲を尊重して最新へ更新(^1.1.1 なら同一 MAJOR 内の最新へ)。lock を更新

CI やデプロイでは npm ci を使うと、毎回まったく同じ依存が入って事故が減ります。

実務の指針

  • ライブラリ作者は semver を守る1.0.0 で公開 API を確定し、互換を壊すなら MAJOR を上げる。0.x の間は「不安定」と明示する
  • アプリは package-lock.json をコミットし、CI で npm ci。範囲の広さに関わらず実バージョンを固定できる
  • ^ のメリットとリスク: バグ修正・機能追加を自動で取り込める反面、提供側が semver を守らないと壊れる。lock があれば実害は出にくいが、lock を持たない/更新する場面では「範囲内の新しい版」が入る点に注意
  • 依存が 0.x なら ^ でも MINOR は上がらないことを前提に置く

まとめ

  • semver は MAJOR(破壊的)・MINOR(互換ある機能追加)・PATCH(互換あるバグ修正)
  • ^ は MINOR まで、~ は PATCH のみ。ただし 0.x では ^0.2.3~ と同じ・^0.0.3 は実質固定
  • プレリリースは範囲からデフォルト除外、ビルドメタデータは順序比較で無視
  • package.json=範囲、package-lock.json=固定の2層。再現性は lock + npm ci で担保
  • npm install は lock を更新しうる、npm ci は lock に厳密追従、npm update は範囲内で最新へ

^~、そして 0.x の特例を理解しておくだけで、「勝手に壊れた」「更新されない」の多くは説明がつきます。範囲は意思表示、固定は lock——この役割分担が要です。

参考リンク

Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

Node.js が一気に塞いだ「TLSホスト名検証バイパス」4種 - 2026年6月の緊急アップデートを読み解く

12

2026年6月18日のNode.jsセキュリティリリースは、HIGH 2件を含む12件のCVEを全アクティブライン(22/24/26)で一斉修正しました。中でも目立つのは、ワイルドカード証明書を回避する CVE-2026-48618(Unicodeドット問題)を筆頭にしたTLSホスト名検証バイパスの集中修正です。なぜ「ホスト名を正しく比較する」だけのことがこれほど壊れやすいのか、各CVEの仕組みと、いま実務でやるべきことを整理します。

pnpm のパッチ機能に潜むパストラバーサル - CVE-2026-50015 とは何か

pnpm のパッチ機能に潜むパストラバーサル - CVE-2026-50015 とは何か

16

2026年6月、pnpm のパッチ適用パイプライン(patchedDependencies / @pnpm/patch-package)に複数のパストラバーサル脆弱性が公開されました。中心となる CVE-2026-50015 は、悪意ある .patch ファイルの diff --git ヘッダに ../ を仕込むと、pnpm install 実行時にパッケージディレクトリ外へ任意ファイルを書き込める問題です。攻撃の仕組み、影響バージョン、修正版、自分が影響を受けるかの確認方法と対処を、GHSA と NVD の一次情報で整理します。

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

Node.jsが年1回のメジャーリリースへ - Node 27からの新スケジュールとLTSの考え方

7

Node.js が 2026年3月の公式発表でリリーススケジュールを変更します。Node 27(2027年)から、メジャーは年1回(毎年4月)に集約され、奇数/偶数の区別を廃止して全リリースが LTS 対象に。早期テスト用の Alpha チャンネル新設、総サポート期間の36か月化など、新旧スケジュールの違いと、Node 26 / Node 27 の位置づけ、運用への影響を Node.js 公式ブログを一次ソースに整理します。