鉴于 ECMAScript 文档中的以下引用和最小的可重现代码示例,
为什么使用.js
Javascript ES 模块导入的文件扩展名会导致ERR_MDOULE_NOT_FOUND
错误时package.json
has "type": "module"
?
From Node.js v16.3.0 文档 - 确定模块系统 https://nodejs.org/api/packages.html#packages_determining_module_system(强调我的)
确定模块系统
当作为初始输入传递给 Node 时,或者当 ES 模块代码中的 import 语句引用时,Node.js 会将以下内容视为 ES 模块:
- 以 .mjs 结尾的文件。
- 当最近的父 package.json 文件包含值为“module”的顶级“type”字段时,以 .js 结尾的文件。
该文档说.js
只要我们将包的类型声明为,文件扩展名就会被视为 ES 模块module
.
现在考虑以下最小的可重复示例.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'
}
但是,如果我改变以下内容
- change
foo.js
to foo.mjs
, and
- 更新
import
in index.js
反射foo.mjs
=> import foo from './foo.mjs';
然后程序就可以正常执行了。
为什么是.mjs
当文档明确指出设置时,在这种情况下需要文件结尾"type": "module"
in package.json
应该意味着节点对待常规.js
像 ES 模块这样的文件?
环境:
$ node -v
v16.3.0
正如所指出的@ASDFGerte 在他们的评论中 https://stackoverflow.com/questions/67851875/why-is-javascript-module-with-js-file-extension-not-found-on-import-unless-fi/67852006#comment119930181_67851875,并在中也有充分解释这是“省略文件扩展名,ES6 模块 NodeJS”的答案 https://stackoverflow.com/questions/63459159/omit-the-file-extension-es6-module-nodejs/63460038#63460038:
在 ES 模块中,文件扩展名是强制性的 https://nodejs.org/api/esm.html#esm_mandatory_file_extensions,所以你不能省略.js
像 CommonJS 中一样的文件扩展名。
这就是我困惑的根源。一旦我包含了文件扩展名,ES 模块就可以工作了。例如,这有效。
index.js
import foo from './foo.js';
该解决方案感觉非常明显,但在不知道确切原因的情况下,CommonJS 约定和 ES 模块之间的这种差异无论如何都会感觉像是一个错误,所以我很高兴了解每个模块系统如何处理其文件扩展名。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)