【发布时间】:2021-06-05 16:53:23
【问题描述】:
鉴于 ECMAScript 文档中的以下引用和最小可重现代码示例,
当package.json 具有"type": "module" 时,为什么使用.js 文件扩展名进行Javascript ES 模块导入会导致ERR_MDOULE_NOT_FOUND 错误?
来自Node.js v16.3.0 documentation - Determining module system(强调我的)
确定模块系统
当 Node.js 作为初始输入传递给 node 或被 ES 模块代码中的 import 语句引用时,Node.js 会将以下内容视为 ES 模块:
- 以 .mjs 结尾的文件。
- 当最近的父 package.json 文件包含值为“module”的顶级“type”字段时,文件以 .js 结尾。
文档说,只要我们将包的类型声明为 module,.js 文件扩展名就会被视为 ES 模块。
现在考虑以下最小可重现示例,说明 .js 文件如何不被视为 ES 模块,除非重命名为 .mjs。
package.json
{
"type": "module"
}
foo.js
export default 'foo module';
index.js
import foo from './foo';
console.log("Hello", foo);
使用上面的文件名和代码,会出现以下错误。
$ node index.js
node:internal/process/esm_loader:74
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/georgep/nodemodulestest/foo' imported from /Users/georgep/nodemodulestest/index.js
Did you mean to import ../foo.js?
at new NodeError (node:internal/errors:363:5)
at finalizeResolution (node:internal/modules/esm/resolve:307:11)
at moduleResolve (node:internal/modules/esm/resolve:742:10)
at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:853:11)
at Loader.resolve (node:internal/modules/esm/loader:89:40)
at Loader.getModuleJob (node:internal/modules/esm/loader:242:28)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:73:40)
at link (node:internal/modules/esm/module_job:72:36) {
code: 'ERR_MODULE_NOT_FOUND'
}
但是,如果我更改以下内容
- 将
foo.js更改为foo.mjs,然后 - 更新
index.js中的import以反映foo.mjs=>import foo from './foo.mjs';
然后程序执行没有错误。
为什么在这种情况下.mjs 文件结尾是必要的,而文档明确指出在package.json 中设置"type": "module" 应该意味着节点将常规.js 文件视为ES 模块?
环境:
$ node -v
v16.3.0
【问题讨论】:
-
在 ESM 中,file extension is mandatory。使用
import foo from './foo.js'。 -
谢谢@ASDFGerte,正如你指出的那样,我也在另一个答案中发现了这个事实:stackoverflow.com/a/63460038/2291928。是的,
.js文件扩展名是强制性的。我误解了 ES Modules 和 CommonJS 之间的这种区别。谢谢!
标签: javascript node.js