以下の内容はhttps://let.blog.jp/tag/importより取得しました。


module の JavaScript を動的にインポートするとき構文エラーの場所がわからない
Node.js を使っていて構文エラーがあったのですが原因の場所がわからなかったです
いつもならファイルと行番号を表示してくれるのですが なぜか表示されません
使ってるツールの都合なのかといろいろ試してたら 単純に Node.js を使うだけでも再現できました
mjs ファイルを動的にロードするとダメみたいです

拡張子によるものではないので type="module" でも同じですがここではわかりやすくするため cjs/mjs の拡張子にします
ロードされる mod.cjs / mod.mjs はどっちも構文エラーになるものです

[mod.cjs]
console.log(1

[mod.mjs]
console.log(1

これらをロードする main.cjs / main.mjs を作ります

[main.cjs]
try {
require("./mod.cjs")
} catch(err) {
console.log("cjs error:", { err })
}

import("./mod.mjs").catch(err => console.log("mjs error:", { err }))

[main.mjs]
await import("./mod.cjs").catch(err => console.log("cjs error:", { err }))
await import("./mod.mjs").catch(err => console.log("mjs error:", { err }))

main のそれぞれを実行します

root@e07f755b37f2:/opt# node main.cjs
cjs error: {
err: /opt/mod.cjs:1
console.log(1
^

SyntaxError: missing ) after argument list
at internalCompileFunction (node:internal/vm:77:18)
at wrapSafe (node:internal/modules/cjs/loader:1290:20)
at Module._compile (node:internal/modules/cjs/loader:1342:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
at Module.load (node:internal/modules/cjs/loader:1212:32)
at Module._load (node:internal/modules/cjs/loader:1028:12)
at Module.require (node:internal/modules/cjs/loader:1237:19)
at require (node:internal/modules/helpers:176:18)
at Object.<anonymous> (/opt/main.cjs:2:5)
at Module._compile (node:internal/modules/cjs/loader:1378:14)
}
mjs error: {
err: SyntaxError: missing ) after argument list
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:168:18)
at callTranslator (node:internal/modules/esm/loader:279:14)
at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:30)
at async link (node:internal/modules/esm/module_job:76:21)
}
root@e07f755b37f2:/opt# node main.mjs
cjs error: {
err: /opt/mod.cjs:1
console.log(1
^

SyntaxError: missing ) after argument list
at internalCompileFunction (node:internal/vm:77:18)
at wrapSafe (node:internal/modules/cjs/loader:1290:20)
at Module._compile (node:internal/modules/cjs/loader:1342:27)
at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
at Module.load (node:internal/modules/cjs/loader:1212:32)
at Module._load (node:internal/modules/cjs/loader:1028:12)
at cjsLoader (node:internal/modules/esm/translators:359:17)
at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:308:7)
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:323:24)
}
mjs error: {
err: SyntaxError: missing ) after argument list
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:168:18)
at callTranslator (node:internal/modules/esm/loader:279:14)
at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:30)
at async link (node:internal/modules/esm/module_job:76:21)
}

どちらの場合でも mjs ファイルをロードしたときは構文エラーの場所が表示されていませんね
構文エラーならエディタ上ですぐにわかるのであまり困らないのですが 今回は高機能なエディタがない環境だったので苦戦しました

ちなみに「動的」なインポートでのみ起きます
静的な import の場合はちゃんとエラーの場所が表示されます

[main-s.mjs]
import "./mod.mjs"
root@e07f755b37f2:/opt# node main-s.mjs
file:///opt/mod.mjs:1
console.log(1
^

SyntaxError: missing ) after argument list
at ModuleLoader.moduleStrategy (node:internal/modules/esm/translators:168:18)
at callTranslator (node:internal/modules/esm/loader:279:14)
at ModuleLoader.moduleProvider (node:internal/modules/esm/loader:285:30)

Node.js バージョンは 18, 20, 21 で確認しましたがどれもこうなるようです
Deno の URL 指定でインポートできる機能が便利
Deno だと Gist に ESM 形式で .js ファイルを置いておけば気軽にインポートして使えるのがすごく便利
npm/yarn でのインストールはいらないから REPL でちょっと試すときでも使える

Node.js も ESM は対応してるけど HTTP(S) は許可されてないからインポートしようとするとエラーになる

Only URLs with a scheme in: file, data are supported by the default ESM loader. Received protocol 'https:'
Chrome 105 で import.meta.resolve() が使えるようになる
https://chromestatus.com/feature/5086507990777856

import.meta に resolve が増えるみたいです
resolve は関数で 引数に渡したモジュールをロードする URL を返してくれるようです

つまりこういうことを自分でやらなくてよくなったということですね

const module_path = "foo/bar.js"
const module_url = new URL(module_path, import.meta.url)

自分の URL からの相対パスの解決以外にも import map を使ったモジュールの URL を知るためにも使えるのかも



以上の内容はhttps://let.blog.jp/tag/importより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14