简体   繁体   English

为什么 Javascript 模块在导入时找不到带有“.js”文件扩展名的模块,除非文件扩展名是 .mjs,尽管 package“类型”是“模块”?

[英]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但是,如果我改变以下

  1. change foo.js to foo.mjs , andfoo.js更改为foo.mjs ,并且
  2. Update the 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.

相关问题 JavaScript ES6 模块基本问题:.mjs 文件扩展名和 MIME 类型 - JavaScript ES6 Module basic question: .mjs file extension and MIME type using.mjs 文件扩展名 js 模块 - using .mjs file extension js modules 在 app.js 中导入 js 文件时出现未知文件扩展名错误,使用类型:package.json 中的模块 - I am getting unknown file extension error while importing a js file in app.js, using type: module in package.json 目标“main”中的意外输出文件类型为 .html(^^^^^^^^^^^^ 文件扩展名必须为 .js、.mjs 或 .cjs) - Unexpected output file type .html in target "main" (^^^^^^^^^^^^ File extension must be .js, .mjs, or .cjs) 为什么模块导入会导致Chrome扩展程序崩溃? - Why is module import crashing Chrome Extension? ERR_MODULE_NOT_FOUND 如果没有.js 扩展 - ERR_MODULE_NOT_FOUND if no .js extension 找不到“ .js”文件扩展名的引擎 - Engine not found for the “.js” file extension 哪个应该有.mjs 扩展名,导入文件或导出文件,或两者兼而有之? - Which should have .mjs extension, the importing file or the exporting file, or both? 省略文件扩展名,ES6 模块 NodeJS - Omit the file extension, ES6 module NodeJS Nodejs - 将 mjs 文件中的内容导入 js 文件或如何在 mjs 文件中使用 require? - Nodejs - import stuff from mjs file into js file OR how to use require in mjs file?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM