javascript - 为什么在导入时找不到具有“.js”文件扩展名的 Javascript 模块,除非文件扩展名是 .mjs,尽管包“类型”是“模块”?
问题描述
鉴于 ECMAScript 文档和最小可重现代码示例中的以下引用,为什么使用.js
文件扩展名进行 Javascript ES 模块导入会在hasERR_MDOULE_NOT_FOUND
时导致错误?package.json
"type": "module"
来自Node.js v16.3.0 文档 - 确定模块系统(强调我的)
确定模块系统
当 Node.js 作为初始输入传递给 node 或被 ES 模块代码中的 import 语句引用时,Node.js 会将以下内容视为 ES 模块:
- 以 .mjs 结尾的文件。
- 当最近的父 package.json 文件包含值为“module”的顶级“type”字段时,以 .js 结尾的文件。
文档说,.js
只要我们将包的类型声明为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'
}
但是,如果我改变以下
- 更改
foo.js
为foo.mjs
, 和 - 更新
import
inindex.js
以反映foo.mjs
=>import foo from './foo.mjs';
然后程序执行没有错误。
为什么在这种情况下文件结尾是必要的.mjs
,当文档明确指出设置应该意味着节点将常规文件视为 ES 模块时?"type": "module"
package.json
.js
环境:
$ node -v
v16.3.0
解决方案
正如@ASDFGerte 在他们的评论中所指出的那样,并且在“省略文件扩展名,ES6 模块 NodeJS”的答案中也得到了充分的解释:
在 ES 模块中,文件扩展名是强制的,所以你不能.js
像在 CommonJS 中那样省略文件扩展名。
这是我困惑的根源。一旦我包含了文件扩展名,ES Modules 就可以工作了。例如,这有效。
index.js
import foo from './foo.js';
解决方案感觉很明显,但在不知道确切原因的情况下,CommonJS 约定和 ES 模块之间的这种差异无论如何都会感觉像是一个错误,所以我很高兴了解每个模块系统如何处理其文件扩展名。
推荐阅读
- java - Java Web 客户端远程连接
- antlr - ANTLR tokenVocab 中的相对路径
- postgresql - 在 Postgreql 中,如何确定 postgres 表中的列是否为 LOB 类型,然后如何找到模式中最大 LOB 值的大小?
- json - 为什么我得到更新的 json 字段转换的信息 ZoneAwarePromise 数据
- flutter - 如何在一个选项卡中向另一个选项卡显示/隐藏浮动操作按钮?
- javascript - 身体和图像的大小差异
- python - 在同一行上的 pytorch-ignite ProgressBar 上编写验证指标
- flutter - Navigator of 和 Navigator pop 的区别
- flutter - 无法生成颤振 apk 文件
- java - 如何检查java字节大小是否超过数据库列大小