当你运行 npm run build 或其他 webpack 相关脚本时,Webpack 会经历以下主要阶段:
1. 配置加载
Webpack 首先会读取 webpack.config.js 中的配置,解析所有自定义设置,包括入口文件、输出路径、加载器、插件等。此时,Webpack 确定了如何处理项目中的资源以及如何构建输出的结构。
2. 创建编译环境
Webpack 根据配置创建编译器对象(Compiler 实例),同时将自定义的插件挂载到编译器上。每一个插件都是基于事件钩子的方式工作,Webpack 会在合适的阶段触发相应事件,使插件实现特定功能。
3. 启动编译
执行Compiler对象的run方法,编译正式开始。Webpack 从配置的入口文件(一个或多个)开始,读取入口模块及其依赖关系。然后对每个模块递归分析、处理,构建出依赖关系图(Dependency Graph)。
4. 模块加载和转换
Webpack 会使用配置中的 Loader 对每个模块进行转换。Loader 是文件的预处理器,用于处理特定类型的文件(如 css-loader、babel-loader、file-loader 等)。通过这些加载器,Webpack 可以处理 JavaScript、CSS、图片、字体等不同类型的资源,并将它们转换为可以被浏览器理解的模块。
5. 生成模块依赖图
Webpack 在处理所有模块和依赖关系的过程中,逐步构建模块依赖图,以完整描述整个项目的模块结构。这使得 Webpack 知道哪些模块最终会打包到一起,哪些模块可以被懒加载或拆分。
6. 代码优化(优化阶段)
Webpack 会根据配置的优化选项对模块代码进行优化,例如:
- Tree Shaking:删除未使用的代码(需要使用 ES6 模块化语法)。
- 代码压缩:如
TerserPlugin进行 JavaScript 代码压缩。 - 代码分割(Code Splitting) :按需分割出独立的模块文件,以便实现懒加载或按需加载。
- Scope Hoisting:将多个模块合并成一个函数作用域,以减少函数调用开销。
7. 生成文件(输出阶段)
在完成所有模块转换、优化之后,Webpack 会将模块打包并输出为静态文件。它会依据配置的 output 选项,将打包结果保存到指定目录(通常是 dist),并对文件进行命名(如带 hash 的文件名)。如果配置了多入口或者代码分割策略,Webpack 会生成多个不同的文件。
8. 插件处理(钩子执行)
插件会在 Webpack 的不同阶段执行自定义逻辑。插件通过监听 Webpack 生命周期钩子实现,比如 beforeRun、emit、done 等。常见的插件有 HtmlWebpackPlugin、CleanWebpackPlugin、MiniCssExtractPlugin 等,用于处理 HTML 文件、清理输出目录、提取 CSS 文件等。
9. 完成构建,生成报告
构建完成后,Webpack 输出构建结果(如构建文件大小、打包耗时等)。在开发环境中,如果使用 webpack-dev-server 或 webpack-dev-middleware,Webpack 还会在构建结束后启动一个本地服务器,实时监听文件变更并重新编译热更新。
简要总结
Webpack 的构建流程可以分为 配置加载、编译准备、模块解析、依赖图生成、代码优化、生成文件、插件处理 和 构建完成 八个主要阶段。在每个阶段,Webpack 会根据配置和插件进行不同的操作,最终输出构建结果。