当前位置: 首页 > article >正文

CommonJS 和 ES Modules 的 区别

CommonJS 和 ES Modules 的 区别

  • 1. CommonJS 和 ES Modules 区别?
    • 1.1 语法差异
      • CommonJS:
      • ES Modules:
    • 1.2. 加载机制
      • CommonJS:
      • ES Modules:
    • 1.3. 运行时行为
      • CommonJS:
      • ES Modules:
    • 1.4. 兼容性和使用场景
      • CommonJS:
      • ES Modules:
    • 1.5 总结
  • 2. node 从什么版本开始支持 ES Modules
  • 3. 那高版本还区分 ES Modules 和 commonjs 吗?是否可以共存
    • 3.1 区分 ESM 和 CommonJS
    • 3.2 互操作性
      • 从 CommonJS 模块导入 ES Module:
      • 从 ES Module 导入 CommonJS 模块:
    • 3.3 共存的注意事项
    • 3.4 总结

说明:本文内容通过和 chatgpt 对话而来。

1. CommonJS 和 ES Modules 区别?

CommonJS 和 ES Modules 是 JavaScript 中最常用的两种模块系统,它们在语法、加载机制和用途上有一些关键的区别。了解这些差异对于开发现代 JavaScript 应用程序非常重要。

1.1 语法差异

CommonJS:

  • 使用 require() 来导入模块。
  • 使用 module.exports 或 exports 来导出模块。
// 导入模块
const express = require('express');

// 导出模块
module.exports = someFunction;

ES Modules:

  • 使用 import 和 export 语法。
  • 支持导入和导出多个值,以及导入整个模块。
// 导入模块
import express from 'express';

// 导出模块
export default someFunction;
// 或导出多个命名导出
export { someFunction, anotherFunction };

1.2. 加载机制

CommonJS:

  • 同步加载模块,这意味着模块在被 require() 调用时立即加载和执行。
  • 适用于服务器端,因为模块文件通常在本地磁盘上,可快速访问。

ES Modules:

  • 支持异步加载,使其更适合用于浏览器端,可以实现动态的导入。
  • 静态结构,可以在编译时进行分析,这有助于进行“树摇”(tree-shaking)以移除未使用的代码。
// 动态导入示例
import('some-module').then((module) => {
  // 使用模块
});

1.3. 运行时行为

CommonJS:

  • 每个模块在第一次被加载时执行,然后其导出的结果被缓存,后续的 require() 调用将返回同一份实例,即模块的单例。
  • 这种缓存机制有助于避免模块的重复执行。

ES Modules:

  • 导入的绑定是实时的,即导入的是一个活的连接,如果模块内部的值变了,导入它的模块也会得到更新的值。
  • 这种行为更类似于引用而非复制,使得模块间的交互更加动态。

1.4. 兼容性和使用场景

CommonJS:

  • 主要用于 Node.js。
  • 在 Node.js 中,CommonJS 是默认的模块系统,直到最近 Node.js 开始支持 ES Modules。

ES Modules:

  • 旨在成为 JavaScript 的官方模块系统。
  • 在现代浏览器中得到原生支持,并且现在 Node.js 也支持 ES Modules,但需要特定的配置(如 type: “module” 在 package.json 中)或使用 .mjs 扩展名。

1.5 总结

选择哪种模块系统通常取决于你的项目需求、目标平台(Node.js、浏览器或两者)以及个人或团队的偏好。ES Modules 由于其设计和特性,被视为未来的标准,但 CommonJS 由于其在 Node.js 中的深入使用和简单性,仍然非常重要和广泛使用。

2. node 从什么版本开始支持 ES Modules

Node.js 对 ECMAScript Modules (ESM) 的支持是逐步实现的,经历了多个版本的迭代和改进。以下是关于 Node.js 如何并在何时开始支持 ES Modules 的简要历史:

Node.js v8.5.0 (2017年): 这个版本首次引入了对 ECMAScript Modules (ESM) 的实验性支持。这需要在运行 Node.js 时使用 --experimental-modules 标志,并且模块文件需要使用 .mjs 扩展名。

Node.js v12.x (2019年): 从 Node.js v12 开始,ESM 的支持得到了进一步增强,并且在 Node.js 12 的后期版本中(特别是 v12.17.0 之后),对 ES Modules 的支持不再需要实验性标志(–experimental-modules)。

Node.js v13.2.0 (2019年): 从这个版本开始,Node.js 允许直接使用 .js 扩展名或 “type”: “module” 在 package.json 中声明来使用 ES Modules,而无需实验性标志。

Node.js v14 (2020年): Node.js v14 将 ES Modules 支持标记为稳定。从这个版本开始,ESM 在 Node.js 中被认为是稳定的,可以在生产环境中安全使用。

因此,可以说 Node.js 从版本 14 开始正式全面支持 ES Modules,而在此之前的版本中,ESM 支持要么是实验性的,要么是有限的。如果你打算在项目中使用 ES Modules,建议使用 Node.js v14 或更高版本以确保最佳兼容性和稳定性。

3. 那高版本还区分 ES Modules 和 commonjs 吗?是否可以共存

在 Node.js 的高版本中,ES Modules (ESM) 和 CommonJS (CJS) 仍然是两种不同的模块系统,它们可以在同一个项目中共存,但是有一些限制和特定的互操作方式需要遵守。下面是一些关键点,帮助理解如何在 Node.js 中同时使用这两种模块系统:

3.1 区分 ESM 和 CommonJS

文件扩展名和package.json的角色:

  • .mjs 文件总是被当作 ES Modules 处理。
  • .cjs 文件总是被当作 CommonJS 模块处理。
  • .js 文件的处理方式取决于其所在的 package.json 中的 “type” 字段。如果 “type” 设置为 “module”,则 .js 文件被当作 ES Modules;如果没有设置或设置为 “commonjs”,则 .js 文件被当作 CommonJS 模块。

3.2 互操作性

从 CommonJS 模块导入 ES Module:

  • 你可以使用 import() 函数动态地从 CommonJS 模块中导入 ES Module。这是一个返回 Promise 的异步操作。
  • 静态 import 语句(例如 import x from ‘module’)不能直接在 CommonJS 模块中使用来导入 ESM。

从 ES Module 导入 CommonJS 模块:

  • 在 ES Module 中,你可以使用静态 import 语句来导入 CommonJS 模块。Node.js 会自动处理 CommonJS 的默认导出,使其可通过默认导入使用。

例如,如果有一个 CommonJS 模块 module.cjs,你可以在 ES Module 中通过 import x from ‘./module.cjs’ 来导入它。

3.3 共存的注意事项

  • 设计和维护:尽管 ESM 和 CommonJS 可以在同一个项目中共存,但建议在新的 Node.js 项目中优先使用 ES Modules,因为它是未来的标准,提供了更好的静态分析和树摇(tree-shaking)能力。
  • 异步与同步加载:ES Modules 总是异步加载的,而 CommonJS 模块是同步加载的。这种差异可能会影响到模块加载和执行的顺序。
  • 依赖管理:在混合使用两种模块系统时,需要特别注意依赖管理和模块解析的规则,以避免出现运行时错误。

3.4 总结

总结来说,虽然 Node.js 支持在同一个项目中同时使用 ES Modules 和 CommonJS,但开发者需要了解两种系统的差异,并小心处理它们之间的互操作性。在长远来看,随着生态系统的发展,逐渐向 ES Modules 过渡将是一个趋势。


http://www.kler.cn/a/417295.html

相关文章:

  • 【iOS自动化】Xcode配置WebDriverAgent
  • 【C#】任务调度的实现原理与组件应用Quartz.Net
  • 62. Linux内核移植
  • 无人机方位感知器官磁力传感器!
  • 第六期:开放银行突围战 - API经济下的跨域经营合规框架
  • mybatis-plus updateById源码
  • uniapp配置全局消息提醒
  • Spring - RabbitMQ循环依赖问题解决
  • 【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-39
  • QT开发准则
  • JS中的类与对象
  • Axios:现代JavaScript HTTP客户端
  • 社交新零售模式下“2+1 链动模式 S2B2C 商城小程序”的创新实践与发展策略
  • flink学习(10)——allowedLateness/测道输出
  • redis快速进门
  • 贪心算法基础解析
  • 【文档搜索引擎】实现索引构建——解析标题、解析URL、解析正文
  • 【西瓜书】支持向量机(SVM)
  • golang append 相关面试题
  • python冒号是什么意思
  • redis基础spark操作redis
  • pycharm报错没有名称为 ‘pytorch‘ 的模块( No module named ‘pytorch‘)
  • 大语言模型LLM的微调中 QA 转换的小工具 txt2excel.py
  • 球幕科技馆:演艺与科技完美融合,打造未来品牌体验—轻空间
  • STM32的CAN波特率计算
  • C#.Net筑基-类型系统