← 返回目录

第 13 卷

第 13 / 26 卷日期:

25产物信息:

26- 入口chunk:${buildStats.entrypoints.main.assets.map(asset => asset.name).join(', ')}

27-总产物大小:${(buildStats.assetsByChunkName.main.reduce((total, asset) => {
28const assetInfo = buildStats.assets.find(a => a.name === asset);
29return total + (assetInfo ? assetInfo.size : 0);
30}, 0) / 1024).toFixed(2)}KB
31错误信息:${buildStats.errors.length > 0 ? buildStats.errors.join('\n - ') :

'无'} 32----------------------------------------

33`;

34 35// 写入日志文件(异步操作)

36fs.writeFile(this.logPath, logContent, { flag: 'a' }, (err) => {
37if (err) {
38console.error('生成构建日志失败:', err);
39} else {
40console.log(`构建日志已生成:${this.logPath}`);
41}
42callback(); //异步钩子必须调用callback,告知Webpack流程结束
43});
44});
45}
46 }

47 48module.exports = BuildLogPlugin;

49

(2)在 Webpack 中使用自定义插件

Code block

1 2// webpack.config.js

3const path = require('path');

4const BuildLogPlugin = require('./BuildLogPlugin');

5 6module.exports = {

7mode: 'production', 8entry: './src/index.js',

9output: {

16logPath: path.resolve(__dirname, 'dist/build-log.txt') //自定义日志路径
17})
18]
19 };

20

(3)效果验证

执行 npx webpack 构建后,会在 dist 目录生成 build-log.txt 文件,包含构建时间、模式、产物大小等信息,实现了自定义的构建日志功能。

十七、Webpack中的依赖图 (Dependency Graph) 是如何构建的?

Webpack 作为静态模块打包器,核心工作之一是构建“依赖图(Dependency Graph)”⸺ 一个描述项目中所有模块(JS、CSS、图片等)及其依赖关系的有向图。依赖图是 Webpack 后续打包、代码

分割、模块替换的基础,其构建过程围绕“入口文件”展开,通过递归解析实现全量依赖收集。

  1. 依赖图的核心作用
  • 明确模块间的依赖关系,确保打包时按依赖顺序加载模块;
  • 支撑代码分割(如提取公共依赖、按需加载),避免冗余打包;
  • 为热更新(HMR)提供模块定位依据,仅更新变化的依赖模块;
  • 辅助 Tree Shaking,识别未被依赖的死代码。
  1. 依赖图的构建流程

依赖图的构建是一个“从入口到深层依赖”的递归解析过程,核心步骤如下:

  1. 初始化:确定入口模块:

Webpack 读取配置中的 entry 选项(可配置单个或多个入口),将入口文件视为“根模块”,作为依赖图的起点。例如 entry: './src/index.js',则 index.js 为根模块。

  1. 解析入口模块:提取直接依赖:
  • Webpack 调用对应的 Loader 处理入口模块(如 JS 文件用 babel-loader 转译,CSS 文件

用 css-loader 解析),将非标准模块(如 ES6+、CSS)转换为 Webpack 可识别的标准模块;

  • 通过“静态分析”提取模块中的依赖声明:对于 JS 模块,解析 import、 require 语句;

对于 CSS 模块,解析 @import、 url() 语句;对于其他资源(如图片),解析 import 或 require 引入的资源路径;

例如: index.js 依赖 utils.js, utils.js 依赖 format.js,则递归解析 index.js → utils.js → format.js,形成完整依赖链。

  1. 模块标识与去重:生成依赖图:
  • 为每个解析后的模块分配唯一的“模块 ID”(如数字 ID 或基于文件路径的哈希 ID),避免模块

重复;

  • 将所有模块及其依赖关系整理为“有向图”结构:以模块为节点,以依赖关系为边,最终形成完

整的依赖图。

例如:依赖图结构可简化为 { 0: { id: 0, file: './src/index.js', dependencies: [1, 2] }, 1: { id: 1, file: './src/utils.js',

dependencies: [3] }, ... }。

  1. 构建过程中的关键细节

• 静态分析的局限性:Webpack 依赖静态分析提取依赖,因此不支持动态依赖声明(如

require(`./${filename}.js`))。对于动态依赖,Webpack 会通过“上下文模块”(Context Module)提前收集可能的依赖模块(如匹配 ./src/*.js 的所有文件),但无

法精准定位到具体模块,可能导致冗余打包。

• 依赖冲突处理:当不同模块依赖同一模块的不同版本时(如 A 依赖 lodash@4.17.0,B 依赖

lodash@4.17.20),Webpack 会在依赖图中为不同版本的模块创建独立节点,通过嵌套安装(早期 npm 模式)或扁平提升(npm 3+、yarn 模式)解决冲突,确保各模块依赖的版本正确。

• Loader 对依赖解析的影响:Loader 不仅转换模块内容,还可能影响依赖提取。例如 sass-

loader 会将 Sass 中的 @import 转换为 Webpack 可识别的依赖声明,确保 Sass 依赖被纳入依赖图。

  1. 依赖图的可视化(辅助调试)

可通过 webpack-bundle-analyzer 插件可视化依赖图,直观查看模块依赖关系和产物体积分布:

Code block

1 2// 安装依赖

3npm install webpack-bundle-analyzer --save-dev
5// webpack.config.js配置
6const BundleAnalyzerPlugin = require('webpack-bundle-
全站分卷索引 · 26 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷
  9. 9第 9 卷
  10. 10第 10 卷
  11. 11第 11 卷
  12. 12第 12 卷
  13. 13第 13 卷
  14. 14第 14 卷
  15. 15第 15 卷
  16. 16第 16 卷
  17. 17第 17 卷
  18. 18第 18 卷
  19. 19第 19 卷
  20. 20第 20 卷
  21. 21第 21 卷
  22. 22第 22 卷
  23. 23第 23 卷
  24. 24第 24 卷
  25. 25第 25 卷
  26. 26第 26 卷