javascript - 为什么在导入时找不到具有 ".js"文件扩展名的 Javascript 模块,除非文件扩展名是 .mjs,尽管包 "type"是 "module"?

标签 javascript node.js

鉴于 ECMAScript 文档中的以下引用和最小的可重现代码示例,
为什么使用 .js Javascript ES 模块导入的文件扩展名导致 ERR_MDOULE_NOT_FOUND package.json 时出错有 "type": "module" ?
来自 Node.js v16.3.0 documentation - Determining module system (强调我的)

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:

  • Files ending in .mjs.
  • Files ending in .js when the nearest parent package.json file contains a top-level "type" field with a value of "module".

文档说 .js只要我们将包的类型声明为 module,文件扩展名就被视为 ES 模块.
现在考虑以下最小的可重现示例,说明 .js除非重命名为 .mjs,否则文件不会被视为 ES 模块.
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.jsfoo.mjs , 和
  • 更新 importindex.js反射(reflect)foo.mjs => import foo from './foo.mjs';

  • 然后程序执行没有错误。
    为什么是.mjs在这种情况下文件结尾是必要的,当文档明确指出设置 "type": "module"package.json应该意味着 Node 对待常规 .js像 ES 模块这样的文件?
    环境:
    $ node -v
    v16.3.0
    

    最佳答案

    正如 @ASDFGerte in their comment 所指出的那样,并且在 this answer to "Omit the file extension, ES6 module NodeJS" 中也有充分的解释。 :
    在 ES 模块中,file extension is mandatory , 所以你不能省略 .js像在 CommonJS 中一样的文件扩展名。
    这是我困惑的根源。一旦我包含了文件扩展名,ES Modules 就可以工作了。例如,这有效。index.js

    import foo from './foo.js';
    
    解决方案感觉很明显,但在不知道确切原因的情况下,CommonJS 约定和 ES 模块之间的这种差异无论如何都会感觉像是一个错误,所以我很高兴了解每个模块系统如何处理其文件扩展名。

    关于javascript - 为什么在导入时找不到具有 ".js"文件扩展名的 Javascript 模块,除非文件扩展名是 .mjs,尽管包 "type"是 "module"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67851875/

    相关文章:

    php - Ajax 文件上传在 Chrome 中有效,但在 Firefox 中无效

    javascript - 使用 npm 编译项目时出错

    javascript - 说明 div 叠加层未显示在 li 图像上

    javascript - "constructor"不打算与构造函数调用一起使用的函数

    mysql - 在 Node js 应用程序中将 <用户名>@<计算机名> 更改为 <用户名>@localhost

    javascript - 使用重组实用程序作为元素

    javascript - 使用 native add_widget 将项目添加到 Gridster.js 网格会导致未知错误

    Ubuntu 上的 Node.js 与 Forever

    javascript - 解码/读取复杂文本文件的json部分

    node.js - 从 node.js 作为一个完整的服务器端新手开始?