基于本文回答
0
评论

Webpack 的构建流程是怎样的?从启动到输出经历了哪些主要步骤?

Webpack 的构建流程是一个基于事件驱动(Tapable)的流水线系统。简单来说,它从入口文件开始,递归地解析所有依赖,通过 Loader 转译文件,通过 Plugin 注入钩子逻辑,最终将所有代码打包成浏览器可执行的 Chunk 并输出为静态资源。

整个构建流程大体可以分为 三个核心阶段初始化阶段编译构建阶段(Compile)输出生成阶段(Output)


一、 详细构建流程(共 8 个主要步骤)

阶段一:初始化阶段(Initialization)

  1. 初始化参数(Initialize Options)

    • 从配置文件(如 webpack.config.js)和 CLI 命令行中读取并合并参数,形成最终的 options 对象。
  2. 创建 Compiler 对象(Create Compiler)

    • 用上一步得到的参数初始化 Compiler 对象。
    • Compiler 是 Webpack 的“大管家”,贯穿整个生命周期,负责管理配置、监听事件和触发构建。
  3. 加载插件(Init Plugins)

    • 遍历配置文件中的 plugins 数组,执行每个插件的 apply 方法,并将 compiler 对象作为参数传入。
    • 插件在此处向 Webpack 的各种钩子(Hooks)注册监听函数,以便在后续阶段干预构建流程。

阶段二:编译构建阶段(Compilation)—— 最核心的阶段

  1. 确定入口(Entry)

    • 根据配置中的 entry 找到所有的入口文件。
    • 触发 compiler.run() 并创建 Compilation 对象(负责代表“这一次”的编译过程)。
  2. 编译模块(Build Module / Loader 处理)

    • 读取文件:从入口文件开始,读取源码。
    • 调用 Loader:根据 module.rules 中匹配的规则,将文件交给相应的 Loader 处理(如 .vue -> JS,scss -> CSS)。Loader 按照从右到左/从下到上的顺序执行,将非 JS 资源转换为 JS 代码或标准的 AST。
    • 解析 AST 寻找依赖:使用 Babel/Acorn 将 Loader 转译后的代码解析成抽象语法树(AST)
    • 收集依赖:分析 AST 中的 importrequire() 等语句,找到当前模块依赖的其他模块。
  3. 递归编译依赖(Recursive Build)

    • 对第 5 步中找到的依赖模块,递归地执行“读取 -> Loader转译 -> 解析AST -> 收集依赖”的过程。
    • 直到所有入口文件及其依赖的所有模块都被编译完成,形成一棵模块依赖图(Module Graph)

阶段三:输出生成阶段(Output)

  1. 合成 Chunk 并渲染(Create Chunks & Assets)

    • 拆分 Chunk:根据入口文件(Entry)以及动态导入(import())、代码分割配置(optimization.splitChunks),将编译后的 Modules 组合成不同的 Chunk(代码块)。
    • 生成 Assets:将 Chunk 转换为对应的代码模板(比如加上 Webpack 独有的模块加载器 __webpack_require__),生成一个个包含最终代码的文件(Assets/Files,此时还在内存中)。
  2. 输出完成(Emit Files)

    • 确定输出路径:根据配置 output.pathoutput.filename,确定文件输出的最终路径和文件名。
    • 写入文件系统:触发 emit 事件(这是修改输出内容的最后机会),然后将内存中的资源文件写入磁盘(Dist 目录)。
    • 触发 done 事件,构建结束。

二、 一图胜千言(流程简图)

plaintext
[ 读取 Config / CLI 参数 ]
          ↓
[ 初始化 Compiler 并挂载 Plugins ]
          ↓
[ 执行 compiler.run() → 创建 Compilation ]
          ↓
[ 从 Entry 节点开始解析 ]
          ↓
[ 匹配 Loader 转换文件内容 (例如 Sass->CSS, ES6->ES5) ]
          ↓
[ 解析 AST,提取 import/require 依赖 ]
          ↓
[ 递归处理所有依赖模块 (形成 Module Graph) ]
          ↓
[ 将 Modules 组合成 Chunks (代码分割/合并) ]
          ↓
[ 使用 Template 渲染 Chunk 成为 Assets (带 Webpack Runtime) ]
          ↓
[ 触发 emit 钩子,将 Assets 写入 Output 硬盘目录 ]
          ↓
[ 完成构建 (done 阶段) ]

三、 两个核心概念:Compiler 与 Compilation

在理解构建流程时,必须区分这两个极其重要的对象:

  1. Compiler

    • 代表: Webpack 的整个生命周期(从启动到关闭)。
    • 全局唯一: 在启动时创建一次。
    • 作用: 保存了 Webpack 的完整配置,暴露了全局生命周期 Hook(如 run, make, emit, done)。
  2. Compilation

    • 代表: 一次单独的编译构建过程
    • 多次创建: 在热更新(HMR)或开发模式下,每次修改文件重新打包时,Webpack 都会创建一个新的 Compilation 对象。
    • 作用: 保存了当前的模块资源(Modules)、依赖图(Module Graph)、 Chunk 以及最终生成的 Asset 信息。

四、 总结(口语化速记)

Webpack 的构建流程可以概括为 3 个词:

  1. 初始化:合并配置,装载插件,准备环境。
  2. 构建(最重):从 Entry 出发,Loader 翻转代码AST 找依赖,递归形成关系树。
  3. 输出:代码打包合并为 Chunk,生成文件写入 Dist
右滑查看面试常问