$ npm install --save react
などのコマンドでパッケージをインストールすると、package.json にはインストールした(その時点での最新)バージョンが記載されますが
そのとき
"dependencies": { "react": "^15.3.2" }
というように、バージョン番号の前に ^
がつきます。
これの意味と、どうしてつくのか調べてみたメモ。
前提
Node.js のパッケージのバージョンは Semantic Versioning (semver) というルールに従っている。
semver は X.Y.Z
という3桁の数字で表されるバージョンで、
- X: major version。後方互換性のない変更の場合にこのバージョンを上げる
- Y: minor version。後方互換性のある変更の場合、このバージョンを上げる
- Z: patch version。後方互換性のあるバグ修正などの場合、このバージョンを上げる
というルールになっている。
^ (キャレット) とは?
このあたりを読む。
https://docs.npmjs.com/misc/semver#caret-ranges-123-025-004
Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple
パッケージのバージョン番号のうち、一番左の非ゼロの値を変更しないようなアップデートを許容する、という意味のよう。
つまり、
- バージョンが 1.2.3 の場合、1.2.3 <= n < 2.0.0
- バージョンが 0.2.3 の場合、0.1.2 <= n < 0.2.0
- バージョンが 0.0.3 の場合、0.0.3 <= n < 0.0.4
というように、対象のバージョンによって挙動が異なる。
そして、npm install や npm update を行ったとき、許容される範囲の中で最新のバージョンをインストールしたりアップデートしたりする。
そのため、package.json だけだとバージョンを完全に固定できているわけではない。
【補足】package.json でバージョンを完全に固定するには?
後述するように ^
をつけないように設定を変更するか、npm shrinkwrap
コマンドを使って npm-shrinkwrap.json
というファイルを生成しておく。
https://docs.npmjs.com/cli/shrinkwrap
// npm-shrinkwrap.json (例) { "name": "react-es6-tutorial", "version": "1.0.0", "dependencies": { "jquery": { "version": "2.2.2", "from": "jquery@2.2.2", "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.2.tgz" }, "marked": { "version": "0.3.5", "from": "marked@0.3.5", "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz" }, "react": { "version": "0.14.7", "from": "react@0.14.7", "resolved": "https://registry.npmjs.org/react/-/react-0.14.7.tgz", "dependencies": { "envify": { "version": "3.4.1", "from": "envify@>=3.0.0 <4.0.0", "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.1.tgz", "dependencies": { "through": { ...
【補足】~ (チルダ)
^
と似たような記号として、~
(チルダ) もある。
https://docs.npmjs.com/misc/semver#tilde-ranges-123-12-1
Allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not.
minor version が明記されていれば patch version のアップデートを許容、明記されていなければ minor version のアップデートを許容。
なので、
~1.2.3
の場合: 1.2.3 <= n < 1.3.0~1.2
の場合: 1.2 <= n < 1.3.0~1
の場合: 1.0.0 <= n < 2.0.0
^ (キャレット) はなぜつくのか?
package.json にデフォルトで ^
がつく挙動はどこで設定しているのだろうか?気になって調べてみた。
どうやら npm config に関係する設定があるらしい。
save-prefix
デフォルトでつく prefix を設定する。
$ npm config get save-prefix ^ # デフォルトを ~ に変更 $ npm config set save-prefix "~" $ npm config get save-prefix ~
save-exact
--save
や --save-dev
したときに prefix をつけるか、あるいは prefix をつけずに package.json に記載してバージョンを完全に固定するかを選べる。
デフォルトは false
。なので prefix がつく。
$ npm config get save-exact false # デフォルトで完全なバージョン固定になるようにする $ npm config set save-exact true
【補足】npm config で設定した値
どうやらこの設定は ~/.npmrc
に保存されているらしい。
.npmrc
はプロジェクトごとに置くことも可能。
https://docs.npmjs.com/misc/config#npmrc-files
^ (キャレット) をつけずにインストールする方法はないのか?
上述したように、npm config で
$ npm config set save-exact true
と設定しておくと、npm install 時の挙動を変更することができる。
あるいは、npm install 時のオプションとしても
--save-exact (略記は -E)
が用意されている。
https://docs.npmjs.com/cli/install
これをつけると、^
なしでインストールできる。
# -SE は --save --save-exact の略
npm i -SE react