ES 模块:JavaScript 模块化的标准方案
什么是 ES 模块?
ES 模块(ES Modules,简称 ESM)是 ECMAScript 2015(ES6)引入的官方模块化规范。
ES 模块 vs CommonJS
| 特性 | CommonJS | ES Modules |
|---|---|---|
| 加载方式 | 同步 | 异步 |
| 执行时机 | 运行时 | 编译时 |
| 导出 | module.exports | export |
| 导入 | require() | import |
| 顶层 this | module.exports | undefined |
基本用法
导出
// utils.js // 命名导出 export const PI = 3.14159; export function add(a, b) { return a + b; } // 默认导出 export default function greet(name) { return `Hello, ${name}!`; }导入
// main.js // 导入命名导出 import { PI, add } from './utils.js'; // 导入默认导出 import greet from './utils.js'; // 重命名导入 import { add as sum } from './utils.js'; // 导入所有 import * as utils from './utils.js';动态导入
// 动态加载模块 async function loadModule() { const module = await import('./utils.js'); console.log(module.add(2, 3)); } // 条件加载 if (condition) { import('./feature.js').then(module => { module.init(); }); }模块解析
文件扩展名
// 必须包含扩展名 import { func } from './utils.js'; // 不能省略 import { func } from './utils'; // ❌绝对路径
// 从 node_modules 导入 import React from 'react'; // 绝对路径导入 import { utils } from '/path/to/utils.js';模块作用域
// 模块顶层变量不会污染全局作用域 const privateVar = 'secret'; // 只有导出的内容才能被外部访问 export const publicVar = 'public';循环依赖
// a.js import { b } from './b.js'; export const a = 'a'; // b.js import { a } from './a.js'; export const b = 'b';在浏览器中使用
<script type="module" src="main.js"></script>// main.js import { greet } from './utils.js'; console.log(greet('World'));在 Node.js 中使用
{ "type": "module" }// package.json 设置后可以使用 ESM import fs from 'fs'; import path from 'path';模块打包
Webpack 配置
module.exports = { entry: './src/main.js', output: { filename: 'bundle.js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' } ] } };Rollup 配置
export default { input: 'src/main.js', output: { file: 'dist/bundle.js', format: 'esm' } };最佳实践
1. 保持导出简洁
// ❌ 不好:导出过多 export const a = 1; export const b = 2; export const c = 3; // ✅ 好:按需导出 export { a, b } from './constants.js'; export { default as c } from './c.js';2. 使用命名导出
// ✅ 推荐:命名导出便于 tree-shaking export function util1() {} export function util2() {}3. 避免循环依赖
// ❌ 不好:循环依赖 // a.js import { b } from './b.js'; // b.js import { a } from './a.js';总结
ES 模块为 JavaScript 提供了标准化的模块化方案:
- 静态分析:支持 tree-shaking
- 异步加载:更好的性能优化
- 标准规范:跨平台兼容
- 清晰语义:明确的导入导出语法
掌握 ES 模块是现代前端开发的必备技能。