什么是ESmodule?
ES Module是ECMAScript 2015(ES6)官方引入的jsvascript模块化标准,他旨在规范JavaScript的模块化方案,解决长期以来社区各种模块化方案,如(commomJs、AMD、UMD)并存带来的混乱问题。
他的设计目标是静态化,使得模块的依赖关系在代码编译阶段(而非运行阶段)就能确定
核心规范与用法
ESModule 的核心非常简洁,主要就是两个命令,export / import
1、导出(export)
用于从模块中导出函数、对象、或原始值,以便其他模块可以通过import使用
命名导出(Named Exports)
一个模块可以有多个命名导出
// utils.js // 方式一:在声明前直接导出 export const apiUrl = 'https://api.example.com'; export function formatDate(date) { // ... 逻辑 } // 方式二:在文件末尾统一导出 const apiUrl = 'https://api.example.com'; function formatDate(date) { /* ... */ } function helperFunction() { /* ... */ } // 这个没有被导出,是模块私有的 export { apiUrl, formatDate }; // 导出多个变量 export { apiUrl as endpoint }; // 使用别名导出
默认导出(Default Export)
一个模块只能有一个默认导出,通常用于导出一个主要的值或者功能
// Logger.js class Logger { log(message) { console.log(`[INFO]: ${message}`); } } // 方式一:直接导出 export default class Logger { /* ... */ } // 方式二:导出已定义的变量 export default Logger; // 方式三:导出匿名值(常见于函数或对象) export default function(config) { /* ... */ }
2、导入(import)
用于导入由另一个模块导出的绑定
导入命名导出
必须使用与导出时相同的名称,或者使用 as 指定别名
// main.js import { apiUrl, formatDate } from './utils.js'; import { apiUrl as endpoint, formatDate } from './utils.js'; // 使用别名 import * as Utils from './utils.js'; // 将所有命名导出作为 Utils 对象的属性引入 console.log(apiUrl); // 直接使用 console.log(Utils.apiUrl); // 通过命名空间对象使用
导入默认导出
名称可以随意指定,不需要大括号
// main.js import Logger from './Logger.js'; // Logger 可以是任意名字 import MyCustomLogger from './Logger.js'; // 这样也可以 const logger = new Logger(); logger.log('Hello Module!');
混合导入
同时导入默认导出和命名导出
// main.js import React, { useState, useEffect } from 'react'; // React 是默认导出,{ useState, useEffect } 是命名导出
3、动态导入(Dynamic Import)
ES2020 引入了动态导入语法 import(),它返回一个 Promise。这使得可以按需加载模块,是实现代码分割的关键。
// 在需要的时候才加载这个模块
button.addEventListener('click', async () => {
const module = await import('./heavy-module.js');
module.doSomethingHeavy();
});
4、主要优势
相比于之前的模块化方案(如commonJs),ES Module 具有压倒性优势
1、静态分析(Static Analysis)
- 是什么:import和export只能在莫i快的顶级作用域使用,不能写在条件判断或者函数中,这种结构是静态的
- 优势:
- 打包工具优化:webpack、rpllup、vite等可以在打包阶段(构建时)就分析出完整的以来树,从而进行高效的 Tree Shaking,一处未被使用的导出代码,从而减小打包体积。
- 确定性:依赖明确,没有魔法般的隐式注入。
2、异步加载与原生支持(Async & Native support)
- 是什么:ES Module在浏览器是原生支持的,通过:
// 默认就是延迟(defer)加载和执行的。 <script type = "module">
- 优势
- 更好的性能,浏览器可以并行加载多个模块,而不会阻塞HTML解析。
- 无需额外的工具:在现在浏览器中可以直接运行,无需使用webpack等打包工具(生产环境推荐打包),
- 动态导入 import() 使得代码分割和按需加载变的非常的简单和原生。
3、严格的模式和行为(Strict module)
- 是什么: ES Moudle 默认在严格模式(use strict)下运行
- 优势:避免了许多代码错误,是代码更安全,更健壮。例如不能意外创建全局变量,this在顶层不再是window,而是underfined
4、循环依赖处理
- 是什么:模块A导入模块B,同时模块B导入导入模块A
- 优势:ES Moudle 的静态设计使得它对循环依赖的处理比commomJs等方案更可预测和合理,它会创建活的绑定(live Bindings),即导出的模块指向的是同一个地址,而不是值的拷贝。
5、面向未来 (Future-Proof)
- 是什么:这是 ECMAScript 语言标准的一部分,而不是社区规范。
优势:作为官方标准,它得到了所有现代浏览器、Node.js 和所有主流构建工具的一致支持,是毋庸置疑的未来。
image.png
总结
ESModule 通过静态化的核心设计,为前端带来了革命性的变化它使得高效的构建优化(tree shaking)成为可能,提供了浏览器支持和更好的语言级一致性,是现代javascript开发不可获取的基础,几乎所有的现代框架(recart、vue、angular)和构建工具(webpack、vite、rollup),都围绕它构建,掌握ES Module是深入学习前端工程化的第一步