首页 > 其他分享 >前端小白也能懂:ES模块和CommonJS的那些事

前端小白也能懂:ES模块和CommonJS的那些事

时间:2024-06-13 20:31:17浏览次数:24  
标签:CommonJS module js 模块 foo ES

在JavaScript的世界中,模块化是构建大型应用的关键。ES模块(ESM)和CommonJS是两种主流的模块系统,它们各自有着不同的特性和使用场景。你了解它们的区别吗?

ES模块 (ESM)

ES模块是 ECMAScript 官方标准的一部分,它使用importexport语句来导入和导出模块。ES 模块是 JavaScript 官方标准的一部分,已被现代浏览器和 JavaScript 运行时(如Node.js)所支持。

主要特点

  1. 静态结构:ES模块在编译时就确定了模块的依赖关系,可以进行静态分析。
  2. 模块作用域:每个模块都有自己的作用域,默认情况下,模块中的变量不会泄漏到全局作用域。
  3. 异步加载:在浏览器环境中,ES模块可以异步加载,有助于提高性能。

模块解析

  • ES模块的文件扩展名通常是 .js.mjs,其中 .mjs 明确表示该文件是一个ES模块。
  • 在Node.js中,你需要在 package.json 中设置 "type": "module" 来启用ES模块支持。

代码示例

// module.js
export function foo() {
    console.log("foo");
}

export const bar = () => {
    console.log("bar");
}

// main.js
import { foo, bar } from './module.js';

foo(); // 输出 "foo"
bar(); // 输出 "bar"

CommonJS模块

CommonJS模块是Node.js默认的模块系统,它使用requiremodule.exports来导入和导出模块。

主要特点

  • 动态结构:CommonJS模块在运行时确定模块的依赖关系,不能进行静态分析。
  • 同步加载:在Node.js中,CommonJS模块是同步加载的。
  • 广泛使用:由于Node.js默认采用CommonJS模块系统,所以在Node.js生态系统中广泛使用。
// module.js
function foo() {
    console.log("foo");
}
module.exports = { foo };

// main.js
const { foo } = require('./module.js');
foo(); // 输出 "foo"

缓存机制

CommonJS模块在第一次加载时会被缓存,后续加载同一个模块时会返回缓存的版本。这有助于提高性能,但也意味着模块的初始化代码只会执行一次。

 // module.js
 console.log("Module loaded");
 module.exports = { foo: "bar" };

 // main.js
 const module1 = require('./module.js');
 const module2 = require('./module.js');
 // 只输出一次 "Module loaded"

循环依赖

CommonJS模块支持循环依赖,但需要注意的是,循环依赖可能会导致模块加载顺序和结果不确定。

 // a.js
 const b = require('./b.js');
 console.log('a.js');
 module.exports = { name: 'module a' };

 // b.js
 const a = require('./a.js');
 console.log('b.js');
 module.exports = { name: 'module b' };

 // main.js
 require('./a.js');
 require('./b.js');
 // 输出顺序: a.js -> b.js

区别

主要的区别如下表所示:

特性ES模块 (ESM)CommonJS模块
语法import / exportrequire / module.exports
加载方式异步 (浏览器)同步
静态分析支持,有利于Tree Shaking不支持,难以优化死代码
Tree Shaking自然支持,提升代码体积优化部分支持(需工具辅助,效果有限)
Top-Level Await支持,便于编写异步初始化代码不支持,需包裹在async函数内
作用域模块作用域,提升封装性文件作用域,可能导致污染全局
使用场景浏览器和现代Node.js (>=13.2, 需配置)传统Node.js及大量现有生态
模块循环依赖处理更为严格,可能导致错误更宽松,但可能隐藏逻辑问题

Tree Shaking 是什么?

  • ES模块自然支持Tree Shaking(枯树摇动),这是一种在打包过程中移除未被引用的代码的技术,有助于减小最终打包文件的体积。这是因为ES模块的静态结构使得编译器能够明确地知道哪些导出没有被使用。
  • CommonJS模块不直接支持Tree Shaking,因为它们是动态加载的。虽然一些现代打包工具如Webpack通过静态分析尝试实现类似Tree Shaking的效果,但可能不如ES模块那样彻底和高效。

Top-Level Await 是什么?

ES模块支持在模块顶层使用await关键字,咱们可以在脚本的最外层直接使用await关键字,等待Promise解析,而不需要将代码封装在async函数内。这在处理异步初始化或者配置加载等场景特别有用。

// example.mjs
console.log('Start');

const response = await fetch('https://juejin.cn/user/2049145406229127');
const data = await response.json();

console.log('Data received:', data);

console.log('End');

CommonJS模块不支持顶层await,在CommonJS模块中,咱们不能在模块的顶级作用域直接使用await。如果非要这样做,那就会遇到语法错误。咱们需要将await放在一个async function内部。

// example.js
console.log('Start');

(async () => {
    const response = await fetch('https://juejin.cn/user/2049145406229127');
    const data = await response.json();
    
    console.log('Data received:', data);
})();

console.log('End');

兼容性

在Node.js中使用ES模块

如果咱们在Node.js项目中使用ES模块,确保在 package.json 中设置 "type": "module",或者使用 .mjs 文件扩展名。

{ 
    "type": "module" 
}

在ES模块中使用CommonJS模块

咱们可以在ES模块中使用 import 语句来导入CommonJS模块,但需要注意模块的默认导出和命名导出的区别。

 // commonjs-module.js
 module.exports = { foo: "bar" };

 // es-module.js
 import commonjsModule from './commonjs-module.js';
 console.log(commonjsModule.foo); // 输出 "bar"

在CommonJS模块中使用ES模块

咱们可以在CommonJS模块中使用 import 语句,但需要使用动态导入语法

 // es-module.js
 export const foo = "bar";

 // commonjs-module.js
 (async () => {
     const esModule = await import('./es-module.js');
     console.log(esModule.foo); // 输出 "bar"
 })();

选择建议

  • 浏览器环境:现代JavaScript开发,优先使用ES模块,因为它们支持支持静态分析和异步加载,有助于提高性能,推荐在浏览器和现代Node.js项目中使用。
  • Node.js项目:- CommonJS模块广泛应用于Node.js生态系统,支持同步加载和动态依赖,更适合传统的Node.js项目。

注意一下,迁移现有项目从CommonJS到ES模块可能需要一定的工作量,包括修改导入导出语句、处理循环依赖问题,以及确保依赖库也支持ES模块

标签:CommonJS,module,js,模块,foo,ES
From: https://blog.csdn.net/weixin_43242942/article/details/139587047

相关文章

  • Python: faces Swap
     #encoding:utf-8#版权所有2024©涂聚文有限公司#许可信息查看:两个头像图片之间换脸#描述:https://stackoverflow.com/questions/902761/saving-a-numpy-array-as-an-image?answertab=votes#Author:geovindu,GeovinDu涂聚文.#IDE:PyCharm2023.1......
  • iperf报错broken pipe和bad file descriptiopn
    在进行iperf测试时,出现了两个错误:(1)iperf3:error-selectfailed:badfiledescriptor(2)iperf3:error-unabletosendconrolmessage:brokenpipe这两个错误都是在客户端出现的。根据iperf源码,分析了这两个错误的调用函数以及可能出错原因。1、iperf简介网络性能评估主......
  • ABC348E Minimize Sum of Distances 题解
    ABC348EMinimizeSumofDistances题目大意给定一棵共\(n\)个节点的树,第\(i\)个点的权重为\(c_i\)。定义\(f(x)\)表示树上所有点到节点\(x\)的距离乘上权重,即\(f(x)=\sum\limits_{i=1}^n(c_i\timesdis(x,i))\)。求\(\min\limits_{u=1}^nf(u)\)。Solve一眼换根......
  • Dragon Boat Festival
    TheDragonBoatFestivalisaspecialholidayinChina.Ithappensonthefifthdayofthefifthmonthinthelunarcalendar.It'satimetorememberanoldpoetnamedQuYuanwholovedhiscountryverymuch.Today,wecelebratetheDragonBoatFesti......
  • es 源码分析&集群原理
    主要分析几个问题:主分片如何确定的:比如3分片2副本,实际会有3*(2+1)=9个分片,主节点创建的时候会根据一定规则分到不同节点,比如同一分片ID不能在同一节点等规则。写入数据中如何进行数据同步:写到主分片所在的节点,主分片所在节点在同步到副本分片所在节点查询是如何进行的,多个......
  • es源码启动
    通过这篇文章,了解ES如何源码启动、如何定位对应请求的实现类。1.准备环境Jdk:17Es:7.17IDEA:2024.1Gradle:8.7安装jdk、idea下载es源码:(我从github下载的7.17.8的代码)https://github.com/elastic/elasticsearch或者:https://gitee.com/mirrors/elastic......
  • Codeforces Round 952 (Div. 4)
    A读入两个字符串,交换第一位即可。B题意给定整数\(n\),求一个整数\(x\),满足:\(2\leqx\leqn\)。\(\displaystyle\sum\limits_{i=1}^ki\cdotx\)最大,其中\(k\)为满足\(kx\leqn\)最大的正整数。思路赛时思路可以直接枚举\(x\)的所有情况,暴力计算答案。......
  • 从ES的JVM配置起步思考JVM常见参数优化
    目录一、真实查看参数(一)-XX:+PrintCommandLineFlags(二)-XX:+PrintFlagsFinal二、堆空间的配置(一)默认配置(二)配置Elasticsearch堆内存时,将初始大小设置为物理内存的一半(重点理解)(三)堆外内存划分说明元空间(Metaspace)JIT编译后代码存放本地内存直接内存JNI内存(四)平常的......
  • kuberbetes-PVC与PV的创建 和绑定
    PVC与PV的创建如下yaml文件apiVersion:v1kind:PersistentVolume#PV是集群中的一块存储,可以由PVC请求并使用。-虚拟存储-实体机的存储、不是容器中的存储metadata:name:postgresql-pvnamespace:ops-systemspec:storageClassName:nfs#指定了与此PV关联......
  • 活动回顾丨飞天技术沙龙 Serverless + AI 专场(上海站)回顾 & PPT 下载
    5月31日“飞天技术沙龙Serverless+AI专场”上海站圆满落幕。活动受众以关注 Serverless技术的开发者、企业决策人、云原生领域创业者为主,活动形式为演讲、动手实操,让开发者通过一个下午的时间增进对Serverless技术的理解,快速上手Serverless,拥抱云计算新范式带来的......