devlog

Node.js 18 で --experimental-specifier-resolution フラグを使う

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