ESM(ESModule)和CJS(CommonJS)

本文深入探讨了ESM(ECMAScript模块)和CJS(CommonJS)的加载机制。ESM采用静态导入和异步加载,支持按需加载,而CJS则是同步加载并使用require。在ESM中,导出可通过default或命名导出,循环引用时引用的是值的引用。CJS中,exports和module.exports用于导出,循环加载时返回部分执行的值。了解这两种模块系统的差异对于优化代码组织和提升性能至关重要。

目录

一、ESM

1.1 import

1.2 export

1.3 循环引用

二、CJS

2.1 require

2.2 exports 和 module.exports

2.3 循环加载

三、附录


一、ESM

1.1 import

  • 编译时加载
  • 按需加载,支持加载部分内容
  • 值的引用
  • 异步加载,有一个独立的模块依赖的解析阶段

1.2 export

导出的三种方式:

// 第一种
export default 123;
// 第二种
export const a = 123;

const b = 3;
const c = 4;
// 第三种
export { b, c };

1.3 循环引用

重点是值的引用

二、CJS

2.1 require

  • 优先缓存加载
  • 同步加载

 GitHub源码

  • 加载整个模块再解析
  • 运行时加载
  • 值的拷贝

2.2 exports 和 module.exports

  • exports是module.exports的一个引用,exports指向的是module.exports
  • exports只能对外暴露单个函数,但是module.exports却能暴露一个类
exports.[function name] = [function name]
moudle.exports= [function name]

2.3 循环加载

CommonJS 模块遇到循环加载时,返回的是当前已经执行的部分的值,而不是代码全部执行后的值

三、附录

参考链接1: 阮一峰

在Node.js项目中混合使用ES Module(ECMAScript Module)CommonJS模块是可行的,但需要根据项目配置Node.js版本进行适当处理。以下是几种实现混合使用的方法: ### 1. 使用Node.js内置支持(Node.js v12+) 从Node.js版本12开始,Node.js原生支持ES Modules,但需要通过文件扩展名`.mjs`来标识ESM文件,而CommonJS则继续使用`.js`扩展名。例如: ```javascript // cjs-file.js (CommonJS) exports.message = 'Hello from CommonJS'; ``` ```javascript // esm-file.mjs (ES Module) export const message = 'Hello from ES Module'; ``` 如果要在CommonJS文件中导入ES Module,则需要使用`import()`函数进行异步加载: ```javascript // cjs-file.js const { message } = await import('./esm-file.mjs'); console.log(message); // 输出: Hello from ES Module ``` 同样地,在ES Module中也可以通过`require`函数导入CommonJS模块,但这要求Node.js运行时环境支持这种互操作性: ```javascript // esm-file.mjs import fs from 'fs'; // 内置模块可以直接导入 const { message } = require('./cjs-file.js'); console.log(message); // 输出: Hello from CommonJS ``` ### 2. 使用构建工具或打包器(如Webpack, Rollup) 构建工具可以将不同类型的模块统一打包成适合部署的单个或多个bundle文件。这些工具通常能够处理混合模块类型,并且提供更灵活的配置选项。例如,在Webpack中,你可以在同一个项目中同时使用`.js`(默认为CommonJS`.mjs`文件,并通过配置来控制输出格式。 ### 3. Babel与TypeScript转换 利用Babel或TypeScript等转译工具,可以将ES6+代码转换为向后兼容的JavaScript版本,包括将ES Modules转换为CommonJS格式。这允许开发者编写现代ESM风格的代码,同时保持与旧版Node.js环境的兼容性。例如,使用Babel配置: ```json { "presets": ["@babel/preset-env"] } ``` 然后,在你的源码中你可以自由地使用`import`/`export`语法,Babel会将其转换为CommonJS形式以便于Node.js执行。 ### 4. 动态导入条件加载 对于某些特定场景,可能需要根据运行时条件动态决定加载哪种类型的模块。这种情况下可以利用`import()`表达式或者`require.resolve()`配合`require()`来实现按需加载。 ### 注意事项 - **Node.js版本**:确保使用的Node.js版本支持所需的ESM特性。 - **性能考量**:异步加载可能会引入额外的延迟,特别是在启动时频繁使用`import()`的情况下。 - **工具链支持**:检查所有依赖项及构建工具是否完全支持ESMCJS的混合使用。 通过以上方法,可以在同一个Node.js项目中有效地混合使用ES ModuleCommonJS模块,从而逐步迁移到ESM或维持现有CJS代码库的同时引入新特性[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值