Package.json解析

type

在 Node.js 项目中,Node.js 会根据文件的扩展名和一些其他的规则来确定一个 JavaScript 文件是 CommonJS 模块还是 ES Module(ES6 模块)。

判断规则:

  1. 文件扩展名

    • 如果文件的扩展名是 .js,Node.js 会将其视为 CommonJS 模块。
    • 如果文件的扩展名是 .mjs,Node.js 会将其视为 ES Module(需要在文件中使用 importexport)。
  2. package.json 中的 “type” 字段

    • 如果在项目的 package.json 文件中设置了 "type": "module",则 Node.js 会将项目中的所有 .js 文件都视为 ES Module。
    • 如果没有设置 "type": "module",则 .js 文件默认为 CommonJS 模块。
  3. 导入语法

    • 如果在一个 .js 文件中使用了 importexport 关键字来定义模块和导出变量或函数,则该文件会被视为 ES Module。
    • 如果使用了 require()module.exports 来导入和导出,则被视为 CommonJS 模块。

示例:

CommonJS 模块

1
2
3
4
5
6
7
8
// commonjsModule.js
const message = 'Hello from CommonJS Module!';

function greet() {
  console.log(message);
}

module.exports = { greet };

ES Module

1
2
3
4
5
6
// esModule.js
const message = 'Hello from ES Module!';

export function greet() {
  console.log(message);
}

package.json 配置

1
2
3
{
  "type": "module"
}

在上述示例中,commonjsModule.js 使用 module.exports 导出,被视为 CommonJS 模块;而 esModule.js 使用 export 导出,被视为 ES Module。

总结

Node.js 根据文件的扩展名和导入导出的语法来判断一个 JavaScript 文件是 CommonJS 模块还是 ES Module。你可以通过设置 package.json 中的 "type" 字段来指定项目中的默认模块类型,或者根据需要选择使用 .js.mjs 扩展名来明确文件的模块类型。

ES Module和CommonJS的兼容性问题

  1. 在CommonJS中使用import语句:

    报错:Cannot use import statement outside a module

  2. 在CommonJS中require(ES Module): require()不支持直接导入ES模块,可以使用动态import()代替require()

  3. 在ES Module中使用require(ES Module)语句:

    1. require()不支持直接导入ES模块,可以使用动态import()代替require()
    2. 支持require(CommonJS)
  4. 在ES Module中使用import CommonJS 正常

https://www.cnblogs.com/ryelqy/p/11763473.html

在CommonJS 模块中不支持require()直接导入 ES Module

当你尝试在一个CommonJS环境中使用require()来导入一个ES模块时,会遇到ERR_REQUIRE_ESM错误,因为require()不支持直接导入ES模块。

在JavaScript中,ES模块(ESM)和CommonJS模块有不同的导入和导出机制。当你尝试在一个CommonJS环境中使用require()来导入一个ES模块时,会遇到ERR_REQUIRE_ESM错误,因为require()不支持直接导入ES模块。

解决方法

使用动态import()代替require(): 动态import()可以在CommonJS模块中使用,它返回一个Promise对象,该对象解析为模块的引用。

1
2
3
4
import('./es6Module.mjs').then((module) => {  
    module.default.foo();  
    module.esFoo();  
});

在ES Module中不支持require()直接导入 ES Module

.mjs 文件中,也是可以使用 require 的,但是有一些需要注意的地方:

  1. 默认限制

    • .mjs 文件中,你可以使用 require,但是有一个默认的限制,就是不能直接使用 require 导入另一个 .mjs 文件,这会导致 ERR_REQUIRE_ESM 错误。
  2. 解决方法

    • 如果需要在 .mjs 文件中导入另一个 .mjs 文件,你可以通过以下两种方式解决:

      a. 使用动态 import()

      • 动态 import() 是 ES Module 的一部分,可以在所有的 CommonJS 模块和 ES Module 中使用。它是更加推荐和灵活的方式来导入模块。
      1
      2
      3
      4
      5
      6
      7
      
      import { createRequire } from 'module';
      const require = createRequire(import.meta.url);
      
      // 使用动态 import() 导入另一个 .mjs 文件
      import('./module.mjs').then(module => {
        // 在这里处理导入的模块
      });
      

      b. 修改文件扩展名

      • 将你的 .mjs 文件改为 .js 文件,然后在该文件中使用 require 导入其他的 .mjs 文件。这样做可能会让 Node.js 将文件视为 CommonJS 模块,而不是 ES Module。
  3. 注意事项

    • 如果你确实需要在 .mjs 文件中使用 require 导入其他 .mjs 文件,请确保理解 Node.js 对 ES Module 和 CommonJS 的处理方式,并根据具体情况选择合适的导入方式。

总结来说,.mjs 文件中可以使用 require,但需要注意不能直接使用 require 导入另一个 .mjs 文件,需要使用动态 import() 或者考虑修改文件扩展名等方法。

tsconfig.json中的"module": “ESNext"和package.json中的"type”: “module”,

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计