2023-05-16
こんにちは。
Node.js でCLIアプリケーションを作ってます。その過程で js ファイルを import できなく困ったのでメモ書きです。
エラーに遭遇した状況
package.json は次のとおりです。
{ "name": "nycmd", "type": "module", // ESModuleで実装 "bin": { "mycmd": "./bin/mycmd.js" // エントリーポイント }, ... }
bin に mycmd
を定義してます。ターミナルで mycmd
コマンドを実行すると ./bin/mycmd.js
が呼ばれます。
./bin/mycmd.js は次のとおりです。
#!/usr/bin/env node import '../dist/cli'
node で起動し ../dist/cli
を import しようとしてます。が、../dist/cli
を import するときエラーがおきます。
ERR_MODULE_NOT_FOUND というエラー
mycmd
を実行すると、次のようなエラーメッセージが表示されました。
$ mycmd node:internal/errors:490 ErrorCaptureStackTrace(err); ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/xxx/dist/cli' imported from /xxx/bin/mycmd.js at new NodeError (node:internal/errors:399:5) at finalizeResolution (node:internal/modules/esm/resolve:326:11) at moduleResolve (node:internal/modules/esm/resolve:945:10) at defaultResolve (node:internal/modules/esm/resolve:1153:11) at nextResolve (node:internal/modules/esm/loader:163:28) at ESMLoader.resolve (node:internal/modules/esm/loader:838:30) at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18) at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40) at link (node:internal/modules/esm/module_job:76:36) { code: 'ERR_MODULE_NOT_FOUND' }
../dist/cli
を見つけられないと言ってます。どうやら拡張子がないと import できないようです。ドキュメントにも記載があります。拡張子をつければ import できます。
#!/usr/bin/env node import '../dist/cli.js' // 拡張子をつける
拡張子をつけたくない
諸々の事情で拡張子をつけたくないときがあるかと思います。そういうとき --experimental-specifier-resolution
フラグが有用です。
たとえば次のように記述します。
#!/usr/bin/env node --experimental-specifier-resolution=node import '../dist/cli' // 拡張子がなくても動く
ドキュメントはこちらです。
ちなみに残念なことに、このフラグは Node.js 19 で削除されてしまいました。
もともと experimental な機能なので、仕方ありませんが。
Warning を隠す
--experimental-specifier-resolution
フラグをつけると、次のような warning が出力されます。
$ mycmd (node:59074) ExperimentalWarning: The Node.js specifier resolution flag is experimental. It could change or be removed at any time. (Use `node --trace-warnings ...` to show where the warning was created)
--no-warnings
フラグでこのメッセージを隠せます。
Links
作成日
2023-05-16
更新日
2023-05-17