[英]Why is Javascript module with ".js" file extension not found on import unless file extension is .mjs despite package "type" being "module"?
Given the following quote from the ECMAScript documentation and minimal reproducible code example, why does using the .js
file extension for an Javascript ES module import cause an ERR_MDOULE_NOT_FOUND
error when package.json
has "type": "module"
? Given the following quote from the ECMAScript documentation and minimal reproducible code example, why does using the
.js
file extension for an Javascript ES module import cause an ERR_MDOULE_NOT_FOUND
error when package.json
has "type": "module"
?
From Node.js v16.3.0 documentation - Determining module system (emphasis mine)来自Node.js v16.3.0 文档 - 确定模块系统(重点是我的)
Determining module system
确定模块系统
Node.js will treat the following as ES modules when passed to node as the initial input, or when referenced by import statements within ES module code:
Node.js 在作为初始输入传递给节点时,或者在 ES 模块代码中的 import 语句引用时,会将以下内容视为 ES 模块:
- Files ending in.mjs.
以.mjs 结尾的文件。
- Files ending in.js when the nearest parent package.json file contains a top-level "type" field with a value of "module".
当最近的父 package.json 文件包含值为“模块”的顶级“类型”字段时,以 in.js 结尾的文件。
The documentation says that a .js
file extension is treated as an ES module as long as we declare our package's type as module
.文档说,只要我们将包的类型声明为 module ,
.js
文件扩展名就被视为 ES module
。
Now consider the following minimal reproducible example of how a .js
file does not get treated as an ES Module unless renamed to .mjs
.现在考虑以下最小可重现示例,说明
.js
文件如何不被视为 ES 模块,除非重命名为.mjs
。
package.json
{
"type": "module"
}
foo.js
export default 'foo module';
index.js
import foo from './foo';
console.log("Hello", foo);
With the above file names and code, the following error occurs.使用上述文件名和代码,会出现以下错误。
$ 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'
}
But, if I change the following但是,如果我改变以下
foo.js
to foo.mjs
, andfoo.js
更改为foo.mjs
,并且import
in index.js
to reflect foo.mjs
=> import foo from './foo.mjs';
index.js
中的import
以反映foo.mjs
=> import foo from './foo.mjs';
Then the program executes without error.然后程序执行没有错误。
Why is the .mjs
file ending necessary in this situation, when the documentation clearly states that setting "type": "module"
in package.json
should mean that node treats regular .js
files like ES modules?为什么在这种情况下
.mjs
文件结束是必要的,当文档明确指出在package.json
中设置"type": "module"
应该意味着节点将常规.js
文件视为 ES 模块?
Environment:环境:
$ node -v
v16.3.0
As pointed out by @ASDFGerte in their comment , and also fully explained in this answer to "Omit the file extension, ES6 module NodeJS" :正如@ASDFGerte 在他们的评论中所指出的那样,并且在“省略文件扩展名,ES6 模块 NodeJS”的答案中也得到了充分的解释:
In ES Modules, file extension is mandatory , so you cannot omit the .js
file extension like you can in CommonJS.在 ES 模块中, 文件扩展名是强制的,所以你不能像在 CommonJS 中那样省略
.js
文件扩展名。
This was the source of my confusion.这是我困惑的根源。 Once I include the file extension, ES Modules work.
一旦我包含了文件扩展名,ES Modules 就可以工作了。 For example, this works.
例如,这有效。
index.js
import foo from './foo.js';
The solution feels pretty obvious, but without knowing the exact reason, this difference between the CommonJS convention and ES Modules would have felt like a bug anyways, so I'm happy to have learned how each module system treats its file extensions.解决方案感觉很明显,但在不知道确切原因的情况下,CommonJS 约定和 ES 模块之间的这种差异无论如何都会感觉像是一个错误,所以我很高兴了解每个模块系统如何处理其文件扩展名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.