ここ数年、Web系制作現場ではnpmのライブラリを使うことがマストになってきています。
npmもv5からpackage-lock.jsonが生成されるようになったため、各環境での依存関係を共有することができるため、v5以前のような各環境で微妙に違うバージョンをインストールしてしまうためにビルドエラーが出るといった事が少なくなりました。
それでも、通常はデフォルトで^(キャレット)
がつくため、バージョンが変わった後に別の人がインストールを行うと、インストールしたバージョンが変わってしまい依存関係も若干変更されることもあります。
※^(キャレット)や~(チルダ)の説明は後述
※npm v6でも起きるかは未検証
新規にライブラリをインストールする場合は、各自npm installする必要があるため問題ないですが、後からインストールした人に合わせてpackage-lock.jsonが変わるとせっかくの依存関係が、個々それぞれ変わってきてしまいます。
これではチーム開発としてあまり意味がありません。
それを解消するためにライブラリのバージョンを固定するということがあります。
.npmrcを使ってプロジェクトごとにバージョンを固定する
コマンドを使った方法もありますが、それだとすべてのプロジェクトで有効化されてしまいます。
それは良い方法とは言えないのでpackage.json
と同一階層に.npmrc
を作成してプロジェクトごとに作成しましょう。
バージョンを固定するには下記の一文を記述するだけです。
save-exact=true
yarnを使っている場合でも同様にバージョンを固定してくれます。
ただし、yarnも古いバージョンだと動作しないかもしれません。
少なくともv1.12.3
では動作しています。
^(キャレット)と~(チルダ)
package.jsonにインストールしたライブラリバージョンには^(キャレット)や~(チルダ)が先頭についていることがあります。
そもそも、npmのライブラリはsemverというバージョンの付け方になっています。
semverはmajor.minor.patch
で表します。
例えば、1.2.10
だとメジャーバージョンが1、マイナーバージョンが2、パッチが10になります。
公式では下記のように定義しています。
- 下位互換のバグ修正 = パッチ
- 下位互換のある新機能追加 = マイナー
- 下位互換のない変更 = メジャー
^(キャレット)
公式のキャレット説明には下記のように書かれています。
Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple
一番左側に存在するゼロを損なわない更新を許容します。
- ^1.2.3の場合: 1.2.3以上、2.0.0未満 (1.2.3 <= n < 2.0.0)
- ^0.2.3の場合: 0.2.3以上、0.3.0未満 (0.2.3 <= n < 0.3.0)
- ^0.0.3の場合: 0.0.3以上、0.0.4未満 (0.0.3 <= n < 0.0.4)
まれにマイナーバージョン以降が変更になると思っている人もいますが、厳密には違うので注意が必要です。
~(チルダ)
公式のチルダ説明には下記のように書かれています。
Allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not.
マイナーバージョンが指定されている場合はパッチバージョンの更新を許容、そうでない場合はマイナーバージョンの更新を許容します。
- ~1.2.3の場合: 1.2.3以上、1.3.0未満 (1.2.3 <= n < 1.3.0)
- ~1.2の場合: 1.2.0以上、1.3.0未満 (1.2.0 <= n < 1.3.0)
- ~1の場合: 1.0.0以上、2.0.0未満 (1.0.0 <= n < 2.0.0)
- ~0.2.3の場合: 0.2.3以上、0.3.0未満 (0.2.3 <= n < 0.3.0)
バージョンに-beta.x
がついている場合は注意が必要です。
~1.2.3-beta.2の場合: 1.2.3-beta.2以上、1.3.0未満 (1.2.3-beta.2 <= n < 1.3.0)となりますが、同パッチのbetaアップデートである1.2.3-beta.4は許容されますが、1.2.4-beta.2の場合は異なるパッチバージョンのプレリリースになるため更新されません。
おまけ
.npmrcはその他にもオプションがあるので興味がある方は公式サイトを確認してください。
いずれ、このブログでも取り上げようと思います。