node.js 8.5.0でオプション付きでes modulesがサポートされた。なので試してみることにした。
テストプログラムは以下のような簡単なものである。
// test.mjs
import fs from 'fs';
const file = fs.readFileSync('./test.mjs','utf-8');
console.log(file);
これを--experimental-modules
付きで実行する。
node --experimental-modules test.mjs
実行するとエラーが発生。
I:\pj\www\html\wwwmaker>node --experimental-modules commands\keywords.mjs
(node:5568) ExperimentalWarning: The ESM module loader is experimental.
{ AssertionError [ERR_ASSERTION]: An invalid error message key was used: ERR_INVALID_PROTOCOL.
at message (internal/errors.js:70:3)
at NodeError (internal/errors.js:29:13)
at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
at Loader.import (internal/loader/Loader.js:61:27)
at Function.Module._load (module.js:462:27)
at Function.Module.runMain (module.js:665:10)
at startup (bootstrap_node.js:201:16)
at bootstrap_node.js:626:3
generatedMessage: false,
name: 'AssertionError [ERR_ASSERTION]',
code: 'ERR_ASSERTION',
actual: undefined,
expected: true,
operator: '==' }
むむ。さすがエクスペリメンタル。。早速バグか。。と思ってググると以下がヒット。
ESM Module: ERR_INVALID_PROTOCOL · Issue #15374 · nodejs/node
どうもWindows 10のファイルパスC:~
がfile://c/~
に変更できないからのようだ。
> const { resolve } = process.binding('module_wrap'); resolve('C:\\main.mjs', 'file://c/')
URL {
href: 'c:\\main.mjs',
origin: 'null',
protocol: 'c:',
username: '',
password: '',
host: '',
hostname: '',
port: '',
pathname: '\\main.mjs',
search: '',
searchParams: URLSearchParams {},
hash: '' }
上のように、プロトコルにc:
が入ってしまい、これで「そんなプロトコルない!!」というエラーを返すようである。
ちなみにubuntu on windows (LSW)では正常に動作した。。
// ubuntu on windows
sfpg@computer:~$ node --experimental-modules ./test.mjs
(node:1094) ExperimentalWarning: The ESM module loader is experimental.
import fs from 'fs';
const file = fs.readFileSync('./test.mjs','utf-8');
console.log(file);
8.5.1では以下のようにエラーメッセージが変更されるようだ。nightly buildで確かめた。。
{ Error [ERR_INVALID_PROTOCOL]: Protocol "i:" not supported. Expected "file:"
at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
at Loader.import (internal/loader/Loader.js:61:27)
at Function.Module._load (module.js:462:27)
at Function.Module.runMain (module.js:665:10)
at startup (bootstrap_node.js:201:16)
at bootstrap_node.js:626:3 [Symbol(code)]: 'ERR_INVALID_PROTOCOL' }
しかしこれで解決かというとそうではない。import
文をコメントアウトしてみる。都合全部コメントアウトになるけど。。
// test.mjs
// import fs from 'fs';
// const file = fs.readFileSync('./test.mjs','utf-8');
// console.log(file);
実行してみると、同じエラーが発生。。
I:\pj\www\html\wwwmaker>node --experimental-modules ./commands/test.mjs
(node:11876) ExperimentalWarning: The ESM module loader is experimental.
{ Error [ERR_INVALID_PROTOCOL]: Protocol "i:" not supported. Expected "file:"
at resolveRequestUrl (internal/loader/resolveRequestUrl.js:84:11)
at Loader.import (internal/loader/Loader.js:61:27)
at Function.Module._load (module.js:462:27)
at Function.Module.runMain (module.js:665:10)
at startup (bootstrap_node.js:201:16)
at bootstrap_node.js:626:3 [Symbol(code)]: 'ERR_INVALID_PROTOCOL' }
実行時に内部的にモジュールをロードしているのだろうと思うんだけど、それがコケてしまっているようだ。 なのでエラーメッセージの変更は根本的な解決ではない。
ちなみに先ほどのissueに、解決案が載っていた。
https://github.com/guybedford/node/commit/cc05513d398491f88421deb878935d096a278db2
これでいけそうな気もするけどね。。
気になるのはこの問題がエラーメッセージの変更だけでCloseになっていること。大丈夫かな。。
いずれにしろちょっと待ちだな。。
9:38 追記
node 9.0.0のnightly-build(v9.0.0-nightly20170916b0d3bec95c)で確認したら、Fixされていた。
とりあえずよかった。しかしこれって--experimental-modules
をつけるとかならず発生するので、テストすればすぐわかるようなものだけどね。
2017/09/30 追記
node 8.6.0でこの問題は解決した。
Bug修正部分のcommit
https://github.com/nodejs/node/commit/c005713d05
8.6.0 Change Log
https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V8.md#8.6.0