Node (module) で .mjs を付与しない executable は作成できない

Published at: 2023/1/27

Node.js でちょっとしたスクリプトを書く場合、 2023 年現在であれば、 ECMAScript module 形式でそれを記述したくなる。

ECMAScript module 形式のファイルであることを示すためには、以下の3つの方法いずれかによって指定が行われなければならない。

  1. .mjs 拡張子をファイルに付与する
  2. package.json にて type: "module" を指定し、かつ、拡張子を .js にする
  3. 標準入力などプロセス外部から与えられる文字列に対する指定オプションとしての --input-type オプション

Modules: Packages | Node.js v19.5.0 Documentation

特に、 2 の方式については、 package.json だけに指定すれば良いかと思いきや、拡張子なしで shebang から実行した場合には、下記の issue に示されるようなエラーが発生する。

node should execute files without extension as ESM if `"type": "module",` is specified · Issue #34049 · nodejs/node · GitHub

Version: v14.4.0 Platform: The node:14 docker container What steps will reproduce the bug? I'm creating a file called foo (without extension) at /app/bin/foo. I have a /app/package.json file with "type": "module",. The foo file has a #!/...

そこから飛べる下記の PR にて議論がなされているが、 wasm 環境等も加わった際の正しい動作が、仕様として上手く定められないため、ひとまず package.json の type フィールドでモジュール形式を指定する場合であっても、 .js 拡張子であることはマストにしている、とのこと。

esm: treat modules with no extension as .js by srolel · Pull Request #34177 · nodejs/node · GitHub

with this change, extensionless modules loaded with esm loader will be loaded with the same behavior as .js files: if "type": "module" is specified, load as an esm module otherwise, load as cjs module Fixes: #34049 Fixes: #33226 Checklist make -j4 test (UNIX), or vcbuild test (Windows) passes tests and/or benchmarks are included documentation is changed or added commit message follows commit guidelines

Tags: nodejs