前端模块化

2022/4/11 前端

# 前端模块化背景

  1. 前端模块化是一种标准,不是实现
  2. 理解模块化是理解前端工程化的前提
  3. 前端模块化是前端项目规范化的必然结果

# 什么是前端模块化?

  1. 将复杂程序根据规范拆分成若干模块,一个模块包括输入和输出
  2. 模块的内部实现是私有的,对外暴露接口与其他模块通信
  3. 一个 HTML 页面可以引用的 script 包括:脚本和模块

# 前端模块化的进化过程

  1. 第一阶段:全局 function 模式,将不同功能封装成不同函数

    1. 缺陷:容易引发全局命名空间冲突
    2. 示例:
      function api() {}
      function handle() {}
      
      1
      2
  2. 第二阶段:全局 namespace 模式,通过对象封装模块

    1. 缺陷:外部能够修改模块内部数据
    2. 示例:
      function api() {}
      function handle() {}
      var __Module = {
          api,
          handle
      }
      
      1
      2
      3
      4
      5
      6
  3. 第三阶段:IIFE 模式,通过自执行函数创建闭包

    1. 缺陷:无法解决模块间相互依赖问题
    2. 示例:
      ;(function (global) {
          var a = 1
          function api() {
              return a
          }
          function handle() {}
          global.__Module = {
              api,
              handle
          }
      })(window)
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
  4. 第四阶段:IIFE 模式增强,支持传入自定义依赖

    1. 缺陷:
      1. 多依赖传入时,代码阅读困难
      2. 无法支持大规模的模块开发
      3. 无特定语法支持,代码简陋
    2. 示例:
      ;(function (global, moduleAPI) {
          function sum() {}
          global.__Module = {
              api: moduleAPI.api,
              handle: moduleAPI.handle
          }
      })(window, window.__Module_API)
      
      1
      2
      3
      4
      5
      6
      7
  5. 第五阶段:CJS、ESM、AMD、CMD

# CJS

  1. 规范介绍

    1. Node.js 默认模块化规范,每个文件就是一个模块,有自己的作用域
    2. Node 中 CJS 模块加载采用同步加载方式
    3. 通过 require 加载模块,通过 exports 或 module.exports 输出模块
  2. 规范特点

    1. 所有代码都运行在模块作用域,不会污染全局作用域
    2. 模块可以多次加载,第一个加载时会运行模块,模块输出结果会被缓存,再次加载时,会从缓存结果中直接读取模块输出结果
    3. 模块加载的顺序,按照其在代码中出现的顺序
  3. 原理

    1. CJS 会在模块外层包一层 IIFE 的函数,并传入 require、module、exports、**filename、 **dirname
    2. CJS 如果使用了 module.exports 进行输出,其他的 exports 输出就会失效
    3. CJS 在浏览器中不可使用,可以通过 browserify 这个进行打包,打包后可以在浏览器中运行

# AMD

  1. 规范介绍
    1. AMD 规范采用非同步加载模块,允许指定回调函数,对比 CJS,AMD 是异步的,CJS 是同步的
    2. Node 模块通常都位于本地,加载速度快,所有适用于同步加载
    3. 浏览器环境下,模块需要请求获取,所有适用于异步加载
    4. require.js 是 AMD 的一个具体实现库
  2. 注意:用的少

# CMD

  1. 规范介绍
    1. CMD 整合了 CJS 和 AMD 的优点,模块加载时异步的
    2. CMD 专门用于浏览器端,sea.js 是 CMD 规范的一个实现
  2. 注意:用的少

# AMD 和 CMD 的问题

  1. AMD 和 CMD 最大的问题是没有通过语法升级解决模块化

# ESM

  1. 规范介绍
    1. ESM 设计理念是希望在编译时就确定模块依赖关系及输入输出
    2. CJS 和 AMD 必须在运行时才能确定依赖和输入输出
    3. ESM 通过 import 加载模块,通过 export 输出模块

# CJS 和 ESM 对比

  1. CJS 模块输出的是值的拷贝,ESM 模块输出的是值的引用(重要!!!)

  2. CJS 模块是运行时加载,ESM 模块是编译时输出接口

  3. CJS 是单个值导出,ESM 可以导出多个

    1. 在 ESM 中 export 和 export default 可以同时生效
    2. 在 CJS 中 exports 和 module.exports 不能同时生效
  4. CJS 模块为同步加载,ESM 支持异步加载

  5. CJS 的 this 是当前模块,ESM 的 this 是 undefined

  6. CJS 和 ESM 语法不同

  7. Node.js 默认采用的模块化规范是 CJS,Node 14 后默认支持 ESM

  8. 浏览器默认采用的模块化规范是 ESM

# HTML 中脚本和模块对比

  1. 模块具备更高的开发效率(可读性强、复用高效)
  2. 脚本具有更高的页面性能(模块文件多,加载速度慢)
  3. 模块在浏览器中运行会存在兼容性问题,要特别注意

# 浏览器模块化的局限

  1. 缺乏模块管理能力,模块分散在各个项目中
  2. 性能加载慢,无法在大型项目中直接使用
  3. 这两个问题是 Npm 和 Webpack 核心解决的问题

# 前端工程化关键技术之 Npm + Webpack

# Npm

  1. 诞生背景

    1. Npm 由程序员 Isaac 发明
    2. 初步思路:
      1. 集中管理所有模块,所有模块都上传到仓库(registry)
      2. 模块内创建 package.json 标注模块的基本信息
      3. 通过 npm publish 发布模块,上传到仓库(registry)
      4. 通过 npm install 安装模块,模块安装到 node_modules 目录
  2. Npm 于 2014 年商业化,2020 年被 Github 收购

  3. Npm 介绍

    1. npm 解决的核心问题是模块管理问题
    2. npm 包含 cli、模块仓库、官网三大部分
    3. npm 仓库分为 public 和 private
      1. public 分为普通仓库和组织仓库(一般以 @ 开头)
      2. private 主要的商业模式
  4. Npm 原理

    1. npm init 创建模块
    2. npm install 安装模块
    3. npm publish 发布模块
    4. npm link 本地开发
    5. npm config 调整配置
    6. npm run 调用 script
    7. npm 规范:package.json 管理模块信息,node_modules 保存依赖
  5. Npm 的局限

    1. npm 只能解决模块的高效管理和获取问题
    2. npm 无法解决性能加载问题
    3. 模块化发明后,制约其广泛应用的因素就是性能问题
    4. 需要 Webpack

# Webpack

  1. 诞生背景
    1. webpack 2012 年 3 月 10 号诞生,作者是 Tobias(德国)
    2. 移植了 GWT(Google Web Toolkit)的功能 code splitting
    3. 2014 年 Instagram 团队分享性能优化时,提到使用 webpack 的 code slitting 特性
    4. webpack 的出现模糊了任务和构建的边界,使之融为一体
  2. 原理
    1. 最初的 webpack 核心解决的问题就是代码合并与拆分
    2. webpack 的核心理念是将资源都视为模块,统一进行打包和处理
    3. webpack 提供了 loader 和 plugins 完成功能扩展

作者:chenjie
链接:https://webchenjie.cn
来源:ChenJieBlog

Last Updated: 2025/3/27 15:56:10
    飘向北方
    那吾克热-NW,尤长靖