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のバージョンを片っ端から試す…そんなことをやってる人にとっては、充分なのです。(私です。)
追加方法
{
"engines": {"node": "14.x"},
}package.jsonに上記のようにバージョンを追加します。
指定したバージョンと違うバージョンでインストールした場合、動かないパッケージがインストールされる前にエラーを出す
このままだと、例えばバージョン14でenginesを指定していても、バージョン11でインストールした時に、インストール時に警告が出るだけです。対応していないパッケージでもインストール自体はできてしまいます。
Unless the user has set the
https://docs.npmjs.com/cli/v7/configuring-npm/package-json#enginesengine-strictconfig flag, this field is advisory only and will only produce warnings when your package is installed as a dependency.
「ユーザーが構成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































