模块开发

什么是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是深入学习前端工程化的第一步

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容