🐥

【package.json】 バージョンにつける「^」「~」は何を意味するのか?

2023/04/08に公開

はじめに

自分の経験してきた開発プロジェクトでは、^チルダはじまりのバージョン指定がされているpackage.jsonが多かったです。
そこで、^~ってなんでつけてるの?
という疑問から色々と調べたことを書いていきます。

package.json
  "dependencies": {
    "react": "^18.2.0", // これ
    "next": "~12.0.2", // これ
    ,,,

^ 表記で破壊的な変更がない範囲で最新バージョンを利用できる

package.json^表記でバージョン指定が多い理由として
packageを破壊的な変更がない範囲で最新の機能を利用できるバージョンにできる(はず)だから、

と考えました。(違ったりしたらコメントください!)

その理由を後述していきます。
前提として、

  • package.jsonの仕様
  • npmの推奨しているセマンティックバージョニングについて
    理解したあと、

package.jsonのバージョン指定方法を説明しながら考えてみます。

前提1: package.json にはバージョン範囲を記述する

package.jsonには

インストールする package の範囲を記述します。

package.lock.jsonには

実際にインストールされている package のバージョン(などの)情報が記載されます。
つまり、node_modulesに入っている package 郡の情報が記載されます。

前提2: npm の推奨しているセマンティックバージョニング

ざっくり、npmはパッケージを
意味のある数字でバージョンを管理しようぜ、ということを推奨しています。
セマンティック(semantic): 意味の, 語義の, 意味論的な
https://docs.npmjs.com/about-semantic-versioning

このセマンティックバージョニングではバージョンを表す3つの数字x.x.x
[major, minor, patch]という意味をもたせています。
それぞれの意味するところは次のようなものです。

  • major: 前のバージョンと互換性を損なう変更をするときに上げる数字
  • minor: 前のバージョンと互換性を持つ新機能追加の変更をするときに上げる数字
  • patch: 前のバージョンと互換性を持つバグ修正の変更をするときに上げる数字

※つまりmajorアップデートでは破壊的な変更を含む可能性が高いということです。

例を用いて考える

3.4.5というバージョンが最新のpackageがあった場合、
セマンティックバージョニングに則れば

  • majorアップデートを3回
  • 3系になって(majorアップデート3回目以降)から
    • minorアップデートを4回
    • patchアップデートを5回

おこなっているpackageということになります。

package.json のバージョン指定方法

~, ^を含めて大きく4つのバージョン指定方法があるようです。
https://www.npmjs.com/package/semver/v/4.3.6

1. バージョンの数字のみ記載

範囲なし(固定)
記載したバージョンをインストールする。

1.2.3: 1.2.3 (記述したバージョンのみ許容)

2. x or *

x, *を記載した箇所のバージョン更新を許容

  • * : >=0.0.0 (どのバージョンの更新も許容)
  • 1.x : >=1.0.0 <2.0.0 (major バージョン以外の更新を許容)
  • 1.2.x : >=1.2.0 <1.3.0 (patch バージョンだけの更新を許容)

3. ~チルダ

minorバージョンが指定されている場合、patchバージョンの変更を許容。そうでない場合は、minorバージョンの変更を許容。

  • ~1.2.3: 1.2.3以上 1.3.0未満
  • ~1: 1.0.0以上 2.0.0未満

4. ^キャレット

3つの数字[major, minor, patch]で1番左側にある0でない数字を変更しない更新を許可。(ややこしい)

  • ^1.2.3:1.2.3以上 2.0.0未満(1の変更は許容しない)
  • ^0.2.3:0.2.3以上 0.3.0未満(2の変更は許容しない)
  • ^0.0.3:0.0.3以上 0.0.4未満(3の変更は許容しない,つまり変更不可?)

つまりmajorバージョンの更新を許容せずに最新バージョンに更新することを許容するようです。

なるほど、つまり

^チルダ表記でバージョン指定をすれば前のバージョンとの互換性を保ちながら、最新バージョンに保たれる可能性が高いといえます。

ただし、セマンティックバージョニングに則っているpackageであること(majorアップデート以外で破壊的な変更がされない)という前提があります。

さいごに

恥ずかしながら今回書いたことは調べるまで知らないことだらけでした。
ライブラリ(package)の開発者も利用者もセマンティック バージョニングについて理解しながら開発をすることが大事だと感じました。

お読みくださりありがとうございました!

参考

参考にさせていただきました。ありがとうございました。

Discussion