※スマホ対応はしてません。

カテゴリー: JavaScript

shrinkwrap はライブラリーでは使わない(NPMおれおれAdvent Calendar 2019 – 09日目)

カテゴリー: JavaScript

HERSHY'SのAdvent Calendar(本物)の9日目を開けたところ。
NPMおれおれAdvent Calendar 2019 – 09日目

shrinkwrap という機能を使って、パッケージがインストールされる際の依存ツリーのバージョンを固定することができます。

できるんだけど、ライブラリーでは使わない方が良さそうです。

強く非推奨

It’s strongly discouraged for library authors to publish this file, since that would prevent end users from having control over transitive dependency updates.

ライブラリー作者がこのファイルを公開することは強く非推奨 (strongly discouraged) です。エンドユーザー側での推移的な (transitive) 依存関係更新による管理の妨げになるためです。

アプリ用

じゃあ何のためかというと、アプリ用です。アプリケーションソフトウェア。例えば CLI で動作するものや、デーモンとして利用されるものです。

The recommended use-case for npm-shrinkwrap.json is applications deployed through the publishing process on the registry: for example, daemons and command-line tools intended as global installs or devDependencies.

npm-shrinkwrap.json の推奨される利用事例は、レジストリー上の公開プロセスを経由してデプロイされるアプリケーションです。例えばグローバルインストールや devDependencies を意図したデーモンやコマンドラインツールが該当します。

というわけでコードから import() するようなものは固定しないようにしましょう。

おしまい

正直「推移的な依存関係更新」というのがよくわかってないんですが、お任せした方が良いようです。

参照

shrinkwrap でパッケージのバージョンを固定できるよ(NPMおれおれAdvent Calendar 2019 – 08日目)

カテゴリー: JavaScript

HERSHY'SのAdvent Calendar(本物)の8日目を開けたところ。
NPMおれおれAdvent Calendar 2019 – 08日目

npm-shrinkwrap.json は package-lock.json と基本的には同一のロックファイルです。

最大の違いは NPM パッケージの一部としてリポジトリーで公開できることです。

ロックファイル?

通常依存パッケージのバージョンは package.json である程度の範囲をもって記述され、インストール時にその範囲内で最新のものが利用されます。

例えば package.json での指示が "^1.2.3" の場合、インストールされうる最低のバージョンは v1.2.3 で、範囲外である v1.2.2 がインストールされることはありません。一方最高のバージョンは v1.999.9999 など v2.0.0 よりは低くなります。

semver や記号の意味についてはまた後日詳しくやりたい。

とまあそういうわけでインストールされ得るバージョンには幅があるんですが、それを固定するのがロックファイルです。

package-lock.json と npm-shrinkwrap.json の違い

中身は完全に同じです。

生成方法等と除くと、最大の違いは npm-shrinkwrap.json は NPM パッケージの一部として公開することが可能で、package-lock.json はそれができないという点です。公開用と開発用って感じだろうか。

作り方

shrinkwrap サブコマンドで生成します。

$ npm shrinkwrap
npm notice created a lockfile as npm-shrinkwrap.json. You should commit this file.

実際のツリーが反映される

生成される npm-shrinkwrap.json は、package.json ではなく実際の node_modules 内のファイル構成を元に生成されます。

例えば、 npm install に --no-save を付けるとパッケージを package.json へ記載することなくインストール可能です。一方で npm shrinkwrap はそのような記載のないパッケージも全て npm-shrinkwrap.json へ反映します。

使い方

npm-shrinkwrap.json を生成したらそれを含めて(というか除外しないで)NPM パッケージ公開 npm publish します。

すると、該当パッケージ利用者がそれを npm instal xxx で導入する際にロックファイルが参照され、それを元に node_modules が構築されます。

逆に、作者側が開発用に npm install を実行すると、npm-shrinkwrap.json は更新されてしまいます。このインストールは package.json の方を参照するので、その結果の node_modules が反映されるという仕組みのようです。ちなみに npm-shrinkwrap.json がなければ package-lock.json が生成されます。

おまけ:英単語 Shrinkwrap とは

shrink は「縮む」、wrap は「包み、ラップ」という意味で、合成して「収縮包装」みたいな意味です。

なんかほらあるでしょ、商品をぴっちり包む透明のフィルム。あれのことみたいです。

バージョンを固定するところがぴっちり感なのかな。

ちなみに shrinkwrap という単語からエビを連想するんだけど、どう見ても shrimp です本当にありがとうございました。

おしまい

初めてなので調べて試して書いてます。なんか違ったらおしえて。

参照

`package-lock.json` はNPMリポジトリーに含まれないよ(NPMおれおれAdvent Calendar 2019 – 07日目)

カテゴリー: JavaScript

HERSHY'SのAdvent Calendar(本物)の7日目を開けたところ。
NPMおれおれAdvent Calendar 2019 – 07日目

そういう仕様です。

先にまとめ

  • package-lock.json は NPM リポジトリーに追加されない
  • つまり依存パッケージとしてインストールされる場合、バージョンは固定されない
  • Git のリポジトリーには含めてください

公開されない

One key detail about package-lock.json is that it cannot be published, and it will be ignored if found in any place other than the toplevel package. It shares a format with npm-shrinkwrap.json, which is essentially the same file, but allows publication.

package-lock.json の鍵となる特徴として、公開されないという点があります。またトップレベルパッケージ以外の場所のものは無視されます。npm-shrinkwrap.json は本質的に同じファイルでありその書式を共有していますが、こちらは公開が可能です。

ここでいう「公開 (publish) 」とは npm-publish のことで、NPM パッケージとして公開するという意味です。公開すると npm install xxx でインストールできるようになります。

というわけで npm install xxx でインストールしたパッケージには package-lock.json は含まれていません。

パッケージとしてはバージョンが固定されない

package-lock.json を利用することで利用中の依存パッケージのバージョンをツリー全体で記録できるのですが、前述のとおり NPM のリポジトリーには登録されないので、インストールされるのは package.json に記載のバージョンが許容する範囲の最新のもの、になります。

つまり、手元で開発する場合にのみ package-lock.json が意味を成すって感じですね。

だからといって使わなくてもいいじゃんみたいな話じゃないです。それは別の日に。

shrinkwrap

npm-shrinkwrap.json は package-lock.json と同じようなものですが、こちらは NPM リポジトリーへ含めることが可能です。

可能ですが、強く非推奨 (strongly discouraged) とされています。

おしまい

偉そうな顔して shrinkwrap 使ったことないので正直肌感がわかってないです。

参照

関連

プロジェクトのクリーンインストールとテストを同時に行うやつ(NPMおれおれAdvent Calendar 2019 – 06日目)

カテゴリー: JavaScript

HERSHY'SのAdvent Calendar(本物)の6日目を開けたところ。
NPMおれおれAdvent Calendar 2019 – 06日目

npm install-ci-test というのがあるのに気付きました。ci と test をまとめてやってくれるとのこと。

This command runs an npm ci followed immediately by an npm test.

翻訳もいらないくらい簡潔な説明だ。これしか載ってない。

あとショートカットとして、npm cit というまさに ci + test という感じのがあります。

クリーンインストールって

npm ci でやるやつです。一度 node_modules を空にして、package-lock.json を元に再構築します。

使いどころ

CI では ci と test とどうせやってると思うんだけど、その 2 行を 1 行にまとめることができますね。フルスペルなら可読性も問題ないかな。

あとはやっぱ git clone 直後にこれ走らせると良いんじゃないでしょうか。しらんけど。

おしまい

見つけたばっかでまだ使ったことないです。

参考

関連

`package-lock.json` のひみつ(NPMおれおれAdvent Calendar 2019 – 05日目)

カテゴリー: JavaScript

HERSHY'SのAdvent Calendar(本物)の5日目を開けたところ。
NPMおれおれAdvent Calendar 2019 – 05日目

(追記:なんか間違ってる気がするので調査中。)

言うほど秘密ってもんでもないですが。

なにそれ

package-lock.json は npm install なんかをすると生成されるファイルで、インストールされているパッケージのツリーを表します。このファイルと npm ci を利用して全く同じツリーを再構築することが可能になります。

困ったちゃん

このファイル自体は便利なものだと思うんですが、困った点がひとつ。「ロック」とう名前に反して何もロックしない点です。

ロックファイルがある状態で npm install すると、そのロックされたバージョンのパッケージ群がインストールされる、というのを期待するんですが、実際はそんなことなく、新しいものがあればそちらをインストールし、逆にロックファイルを更新します。ロックとは。

昔はロックしていた

大昔はこの package-lock.json はなく、package.json だけでした。でも package.json だとバージョンに幅を持たせた指定ができて、それはそれで便利だけどバージョンをロックもしたいよねってんでロックファイルを導入されます。

すると package.json の更新をしても実際のパッケージが更新されなくて困った、という問題があったようです。そりゃあロックしてるからな。

どうすんの

npm install の代わりに npm ci を利用してください。こちらであればロックファイルに記載のバージョンを利用してインストールが行われます。

ただし互換機能ではないので、違いには気を付けてください。こちらをどうぞ。

FAQ

package-lock.json ってなに

node_modules がどうなってるかっていう記録です。

package.json と何が違うの?

package.json はプロジェクトにまつわる諸々を載せるもので、よく自分で編集します。依存パッケージのバージョンも記載されますが、例えば "^1.0.0" のように幅のあるバージョンを指定することができます。

package-lock.json は npm が自動出力するもので、パッケージの依存関係がツリー状に保存されます。バージョンは node_modules に実際に置かれているものが記載されます。

Git リポジトリーで管理すべき?

はい。

CI で利用できるし、何か問題があったときに巻き戻すのにも使えます。

なんか git clone からの npm install で変更されちゃったんですけど?

そういうもんです。以下の選択肢があります。

  • 変更を戻してから、代わりに npm ci を利用して、プロジェクトとして現在採用されているバージョンのパッケージ群をインストールする
  • 変更を戻さずに、そのままコミットして利用バージョンを更新する

なんで npm install でロックファイルが変わるの?

package.json におけるパッケージのバージョンに幅がある場合、インストール時点で指定範囲に収まるうち最新のものがインストールされます。そのため過去の実行時よりも新しいバージョンが出ているならそちらがインストールされ、またそれに合わせてこのロックファイルが更新されてしまいます。

まあロックっていう名前が良くないよね。

編集していい?

だめ

Git でコンフリクトした

package-lock.json を削除して npm install すればちゃんとした状態でまるっと復活します。

package.json 無事でないならさきにそっちを解消してから、同じ手順です。

まとめ

  • npm install は node_modules から package-lock.json を生成する
  • npm ci は package-lock.json から node_modules を構築する

おしまい

なんか違ってたらごめん。

参考

履歴

  • 2019-12-08
    • npm ci に関する記述をもっと追加
  • 2019-12-05
    • 公開