Webpack的构建流程
webpack的构建流程是一个将模板经过解析,转换,优化后,最终打包为浏览器可识别的静态资源 的过程。其核心是围绕"模板"和"依赖"展开,通过插件(plugin)和加载器(loading)扩展功能,整体流程分为初始化,编译,输出三大阶段
初始化
核心任务:读取配置、初始化compiler实例,准备构建环境。
-
**读取配置:**Webpack 从三个来源整合配置信息:
- 配置文件(如
webpack.config.js); - 命令行参数(如
webpack --mode production); - 默认配置(未指定时使用的内置规则)。最终合并为一个完整的配置对象(
options)。
- 配置文件(如
-
创建 Compiler 实例: Compiler 是 Webpack 的核心对象,全局唯一,贯穿整个构建生命周期,负责调度构建流程、管理插件和钩子(hooks)。
-
**加载插件:**遍历配置中的plugins数组,调用每个插件的apply方法,让插件注册到Compiler的钩子上。
编译
核心任务:从入口文件开始,递归解析所有模块及其依赖,转换模块内容,生成依赖图(Dependency Graph)
-
开始编译(run/watch)
调用
compiler.run()(或watch模式)触发构建,Compiler 会创建一个 Compilation 实例(每次构建对应一个 Compilation,负责本次构建的具体工作)。 -
确定入口(Entry)
根据配置的
entry(如{ main: './src/index.js' }),将入口文件标记为 "初始模块",作为依赖解析的起点。 -
模块解析与加载(Module Resolution & Loading)
对每个模块(包括入口模块及其依赖的模块)执行以下操作:
- 路径解析 :根据
resolve配置(如extensions、alias)确定模块的真实路径(如./utils→./utils.js)。 - 加载模块 :根据模块类型(如
.js、.css、.png),匹配对应的 Loader 进行转换:- 例如:
.js文件可能通过babel-loader转译 ES6+ 语法; .css文件通过css-loader处理@import和url(),再通过style-loader注入到 DOM;- 转换后的模块内容会被处理为浏览器可识别的代码(通常是 JS 模块)。
- 例如:
- 路径解析 :根据
-
依赖收集(Dependency Collection)
解析转换后的模块代码,提取其中的依赖(如
import、require语句),递归重复步骤 3(模块解析与加载) ,直到所有依赖的模块都被解析。最终形成一张依赖图(Dependency Graph),记录所有模块的依赖关系。
模板优化
核心任务:对已解析的模块和依赖图进行优化,提升输出资源的性能。
-
生成 Chunk 根据依赖图,将模块按规则合并为 Chunk(代码块):
- 入口模块会对应一个初始 Chunk(如
main入口生成main.js对应的 Chunk); - 通过
splitChunks配置进行代码分割(如提取公共模块、第三方库到单独 Chunk)。
- 入口模块会对应一个初始 Chunk(如
-
优化操作
- Tree Shaking:移除未被使用的代码(依赖 ES6 模块的静态结构);
- 代码压缩 :通过
terser-webpack-plugin压缩 JS,css-minimizer-webpack-plugin压缩 CSS; - 模块合并:将多个小模块合并为一个 Chunk,减少请求次数;
- Hash 生成 :为 Chunk 生成哈希值(如
contenthash),用于缓存控制(文件内容不变则哈希不变)。
输出
核心任务:将优化后的 Chunk 写入到磁盘,生成最终的静态资源。
-
确定输出路径与文件名 根据
output配置(如path: './dist'、filename: '[name].[contenthash].js'),确定每个 Chunk 的输出路径和文件名。 -
生成资源(Assets) 将 Chunk 转换为具体的文件(如
.js、.css、.png等),并可能生成辅助文件:- Source Map(用于调试,如
devtool: 'source-map'); - 清单文件(如
manifest.json,记录 Chunk 与文件的映射关系)。
- Source Map(用于调试,如
-
写入磁盘 通过
fs模块将生成的资源写入到output.path指定的目录(如dist文件夹)。 -
完成构建 触发
done钩子,输出构建成功信息(如构建时间、生成的文件列表)。
plugin和loader
loader
Webpack 本身 只能解析 JS 和 JSON 文件 ,而前端项目中存在大量非 JS/JSON 资源(如 CSS、TS、Vue 单文件、图片、Less/Sass 等)。loader 的核心使命就是:将这些非标准文件 "翻译" 成 Webpack 能理解的模块,再参与后续打包。
工作原理
- 按配置的
test规则匹配目标文件(如.ts匹配 TypeScript 文件); - 对文件内容进行转译 / 处理(如 TS → ES6、Sass → CSS);
- 输出处理后的内容(通常是 JS 模块或可被其他 loader 继续处理的内容);
- 支持链式调用(如
sass-loader → css-loader → style-loader,从后往前执行)。
执行时机
模块解析阶段(Webpack 读取文件时)
链式顺序:
use 数组中 loader 按「从后往前」执行(如 sass-loader 先处理,再交给 css- loader);
功能范围
单一文件的 "转译 / 处理"(输入文件 → 输出模块)
plugin
plugin 不直接处理文件,而是作用于 Webpack 构建的整个生命周期(从编译开始到输出结束的各个阶段),通过「钩子机制」实现各种扩展功能。比如:生成 HTML 文件、压缩代码、清理输出目录、注入环境变量等。
工作原理
- Webpack 构建过程会触发一系列「钩子事件」(如
compile开始编译、emit准备输出文件、done构建完成); - Plugin 本质是一个带有
apply方法的类,通过apply方法注册到 Webpack 钩子上; - 当钩子触发时,Plugin 执行对应的逻辑(如
emit阶段修改输出文件、done阶段打印构建耗时)
执行时机
构建生命周期的特定钩子(如 compile、emit、done 等)
功能范围
全局流程的 "增强"(如生成 HTML、压缩代码、清理 dist 等)