Blog

package.jsonのenginesで作業するnodeのバージョンを指定

以前、「Nodeバージョン管理ツール 【nodebrew / n / nodenv】」という記事を書きました。

やっぱり圧倒的に「n」が使いやすい。

しかし、nodenvの、「ローカルにnodeのバージョンを強制するファイルを作成できる」

nodenv local バージョン

のコマンドが便利だったんですよね…(コマンドが便利というよりこの機能が便利)

そこで、「n」でこういうことができないかと探しました。

探っていくと、同じことはできなかったのですが、「インストール時のnodeのバージョンを記録しておける」という点で、package.jsonにenginesというキーがあったので、これでいいじゃないか…と思い、今回試してみることにしました。

…というわけで、結果的にnは関係ないです。package.jsonでデフォルトでこういう指定ができることや、他にもたくさんの設定ができることを、公式を眺めて知りました。

nodenvの場合は、.node-versionというファイルによって、このプロジェクトで作業するときはこのバージョンがグローバルのバージョンをオーバーライドしてくれます。
今回やるenginesを使ったやり方ではそこまではできず、「インストール当時のnodeのバージョンが確認できる」という程度になります。

しかしこれで充分です。npm run gulpとかnpm run dev の時にエラーがでて、「ああ…この案件はどのバージョンでインストールしたんだっけ…」と、nodeのバージョンを片っ端から試す…そんなことをやってる人にとっては、充分なのです。(私です。)

npm package.json

追加方法

{
  "engines": {"node": "14.x"},
}

package.jsonに上記のようにバージョンを追加します。

指定したバージョンと違うバージョンでインストールした場合、動かないパッケージがインストールされる前にエラーを出す

このままだと、例えばバージョン14でenginesを指定していても、バージョン11でインストールした時に、インストール時に警告が出るだけです。対応していないパッケージでもインストール自体はできてしまいます。

Unless the user has set the engine-strict config flag, this field is advisory only and will only produce warnings when your package is installed as a dependency.

https://docs.npmjs.com/cli/v7/configuring-npm/package-json#engines

「ユーザーが構成engine-strictフラグを設定していない限り、このフィールドは通知のみであり、パッケージが依存関係としてインストールされている場合にのみ警告を生成します。」

できたらエラーで知らせてほしいので、engine-strictフラグを設定します。

余談ですが、もともとはpackage.jsonにengineStrictを設定できたらしいですが、どうやらなくなったようです。

ちょっと古いドキュメントをみると

本当に、全くもって動かない場合以外はこの設定を行わないで下さい。 あまり大袈裟に拒否すると、ついうっかり動作を限定してしまったり、 ユーザーの新しい node へのバージョンアップを妨げてしまうことがあります。 設定には十分に考慮してください。もし乱用が見受けられれば、将来的に npm の機能として取り除きます。

npm package.json 取扱説明書(日本語)

とあります。この言葉の通り、なくなったようです。

ではどこで設定するのかというと、「.npmrc」を使います。
.npmrcというものを初めて知ったのですが、npmの設定をプロジェクトごとに設定できるようです。

.npmrcを作り、

engine-strict=true

と設定を入れて保存。プロジェクトフォルダに入れておきます。

再インストールしてみると
(package-lock.jsonがあったら削除しておく)

エラーが出ました。

Not compatible with your version of node/npm: mypackage@1.0.0
ご使用のバージョンのnode / npmと互換性がありません:mypackage@1.0.0

これで通知を見逃してインストールすることを防ぐことができます。

nodenvからnに切り替える時につまづいたこと

ここからは個人的につまづいたところですが、今までnodenvを使っていてnをインストールしようとすると、
インストール先がnodenvの中になってしまうということがおきました。

nのインストール(グローバルへ)

npm i n -g

すると、

/Users/cumak/.anyenv/envs/nodenv/versions/14.17.0/bin/n -> /Users/cumak/.anyenv/envs/nodenv/versions/14.17.0/lib/node_modules/n/bin/n

なぜグローバルインストールでここにインストールされる…。

理由は、anyenvを入れた時にシェル初期化ファイルに書いていたこれ

export PATH="$HOME/.anyenv/bin:$PATH"
eval "$(anyenv init -)"

anyenvの初期化処理です。
コメントアウトしました。その後シェルを再起動し、

exec $SHELL -l

その後nをインストールすると、

/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n

無事グローバルのディレクトリに入りました。(ユーザーディレクトリより上になるので、これが嫌な人は別に設定が必要です)

さらにnodenvのnodeのバージョンをnのフォルダにコピーしてきました。
nのコマンドでインストールしてきてもいいのですが、数も多かったのでやってみたら、nとしてはフォルダが存在すれば認識するようでした。

まとめ

これで、nを使いつつ、nodeのバージョンで迷わずに済む…と思います。

参考

https://blog.yukung.org/difference-between-the-behavior-of-yarn-and-npm-for-engine/
https://qiita.com/terrierscript/items/86dbfd26abe6905756c0#engine-stricttrue

おすすめの記事 recommend blog

新着 new blog

github