Webpack stats 详解(图文+注释)

2024-11-20
webpack
322

介绍

通过 webpack 编译源文件时,用户可以生成包含有关于模块的统计数据的 JSON 文件。这些统计数据不仅可以帮助开发者来分析应用的依赖图表,还可以优化编译的速度。

这个 JSON 文件可以通过以下的命令来生成:

npx webpack --json > stats.json

# 指定config
npx webpack --config config.js --json > stats.json

详情

打开 stats.json,其文件目录如下

stats-struct.png

从文件中可以看出如下信息

stats-attributs

字段名 说明
version Webpack 的版本号。
hash 构建的唯一哈希值,用于标识此次构建。
time 构建耗时,单位为毫秒。
builtAt 构建完成的时间戳。
publicPath 输出文件的公共路径。
outputPath 输出文件的目录路径。
assets 构建生成的文件列表,包含文件名、大小等信息。
entrypoints 入口点及其对应的资源文件。
chunks 生成的代码块信息,包括名称、大小、包含的模块等。
modules 所有模块的详细信息,如路径、大小、依赖等。
errors 构建过程中的错误信息。
warnings 构建过程中的警告信息。
children 子编译过程的 stats 信息,常用于多配置构建。

modules、chunks 和 assets 的关系

以一个简单的例子来说明三者之间的关系

modules、chunks 和 assets 的关系

Modules(模块)

  • 定义: 模块是 Webpack 处理的基本单位,通常是项目中的每个文件(如 JavaScript、CSS、图片等)。

  • 作用: Webpack 会根据模块之间的依赖关系构建依赖图。

  • 特点:

    • 每个模块包含路径、大小、依赖的模块等信息。

    • 模块是 Webpack 构建的最小单位。

  • 示例:

    • ./src/index.js

    • ./src/components/Button.js

    • node_modules/lodash/index.js

  • stats 的数据结构

const a = {
  type: "module", // 模块的类型,表示这是一个 ES 模块(ESM)
  moduleType: "javascript/auto", // 模块的具体类型,表示是 JavaScript 文件且由 Webpack 自动处理
  layer: null, // 模块所属的层,通常用于多层级构建(如微前端),`null` 表示没有指定层
  size: 486, // 模块的大小(字节)
  sizes: { javascript: 486 }, // 模块按类型划分的大小,表示 JavaScript 部分大小为 486 字节
  built: true, // 模块是否已被构建,`true` 表示已构建
  codeGenerated: false, // 模块是否生成了代码,`false` 表示未生成代码(可能是被 Tree Shaking 移除或未使用)
  buildTimeExecuted: false, // 模块是否在构建时执行,`false` 表示未在构建时执行
  cached: false, // 模块是否被缓存,`false` 表示未被缓存
  identifier: "<project>/node_modules/.pnpm/vue-loader@17.4.2_vue@3.5.12_webpack@5.96.1/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[10].use[0]!<project>/apps/bbw/src/views/cash/records/index.vue", // 模块的唯一标识符,包含完整路径和加载器信息
  name: "./src/views/cash/records/index.vue", // 模块的名称,通常是相对路径
  nameForCondition: "<project>/apps/bbw/src/views/cash/records/index.vue", // 用于条件判断的模块名称,通常是绝对路径
  index: 243, // 模块在构建过程中的索引
  preOrderIndex: 243, // 模块在依赖树预序遍历中的索引
  index2: 257, // 模块的另一种索引,通常用于内部优化
  postOrderIndex: 257, // 模块在依赖树后序遍历中的索引
  cacheable: true, // 模块是否可缓存,`true` 表示可以被缓存
  optional: false, // 模块是否是可选的,`false` 表示不是可选的
  orphan: false, // 模块是否是孤立的,`false` 表示不是孤立的
  dependent: true, // 模块是否依赖于其他模块,`true` 表示依赖于其他模块
  issuer: "<project>/node_modules/.pnpm/ts-loader@9.5.1_typescript@4.9.5_webpack@5.96.1/node_modules/ts-loader/index.js??clonedRuleSet-1!<project>/apps/bbw/src/router/index.ts", // 引用该模块的模块标识符
  issuerName: "./src/router/index.ts", // 引用该模块的模块名称
  issuerPath: [ // 引用链路径,表示从入口模块到当前模块的引用链
    {
      identifier: "<project>/node_modules/.pnpm/ts-loader@9.5.1_typescript@4.9.5_webpack@5.96.1/node_modules/ts-loader/index.js??clonedRuleSet-1!<project>/apps/bbw/src/main.ts",
      name: "./src/main.ts",
      id: null
    },
    {
      identifier: "<project>/node_modules/.pnpm/ts-loader@9.5.1_typescript@4.9.5_webpack@5.96.1/node_modules/ts-loader/index.js??clonedRuleSet-1!<project>/apps/bbw/src/router/index.ts",
      name: "./src/router/index.ts",
      id: null
    }
  ],
  failed: false, // 模块是否构建失败,`false` 表示构建成功
  errors: 0, // 模块构建过程中的错误数量,`0` 表示没有错误
  warnings: 0, // 模块构建过程中的警告数量,`0` 表示没有警告
  id: null, // 模块的唯一 ID,`null` 表示未分配 ID
  issuerId: null, // 引用模块的唯一 ID,`null` 表示未分配 ID
  chunks: [], // 模块所属的代码块(Chunk)列表,空数组表示未分配到任何 Chunk
  assets: [], // 模块生成的资源(Asset)列表,空数组表示未生成任何资源
  reasons: [], // 模块被引入的原因,空数组表示没有额外的引入原因
  usedExports: true, // 模块是否使用了导出的内容,`true` 表示使用了导出的内容
  providedExports: ["default"], // 模块提供的导出内容,表示导出了 `default`
  optimizationBailout: [ // 模块优化失败的原因
    "Dependency (harmony side effect evaluation) with side effects at 1:0-67"
  ],
  depth: 2 // 模块在依赖树中的深度,`2` 表示深度为 2
}

Chunks(代码块)

  • 定义: Chunk 是由一个或多个模块组成的代码块,是 Webpack 打包后的输出单位。

  • 作用: Webpack 根据入口点(entry points)和代码分割策略(如 SplitChunksPlugin)将模块分组为 Chunk。

  • 特点:

    • 一个 Chunk 可以包含多个模块。

    • Chunk 是最终生成的 JavaScript 文件的基础。

  • 示例:

    • 入口 Chunk:main.js(包含入口模块及其依赖)。

    • 异步 Chunk:src_components_Button_js.js(通过动态导入生成的代码块)。

  • stats 中的数据结构:

{
  "entry": true, // 表示这个 chunk 是否包含 webpack 的运行时
  "files": [
    // 一个包含这个 chunk 的文件名的数组
  ],
  "filteredModules": 0, // 见上文的 结构
  "id": 0, // 这个 chunk 的id
  "initial": true, // 表示这个 chunk 是开始就要加载还是 懒加载(lazy-loading)
  "modules": [
    // 模块对象 (module objects)的数组
    "web.js?h=11593e3b3ac85436984a"
  ],
  "names": [
    // 包含在这个 chunk 内的 chunk 的名字的数组
  ],
  "origins": [
    // 下文详述
  ],
  "parents": [], // 父 chunk 的 ids
  "rendered": true, // 表示这个 chunk 是否会参与进编译
  "size": 188057 // chunk 的大小(byte)
}

chunks 对象还会包含一个 来源 (origins) ,来表示每一个 chunk 是从哪里来的。 来源 (origins) 是以下的形式

{
  "loc": "", // 具体是哪行生成了这个chunk
  "module": "(webpack)\test\browsertest\lib\index.web.js", // 模块的位置
  "moduleId": 0, // 模块的ID
  "moduleIdentifier": "(webpack)\test\browsertest\lib\index.web.js", // 模块的地址
  "moduleName": "./lib/index.web.js", // 模块的相对地址
  "name": "main", // chunk的名称
  "reasons": [
    // 模块对象中`reason`的数组
  ]
}

webpack stats chunks1

webpack stats chunks2


Assets(资源)

  • 定义: Assets 是 Webpack 最终输出的文件,通常是由 Chunk 经过处理后生成的。

  • 作用: Assets 是浏览器实际加载的资源文件。

  • 特点:

    • 一个 Chunk 可能会生成一个或多个 Assets(如 JavaScript 文件、CSS 文件、Source Map 等)。

    • Assets 是构建结果的最终表现形式。

  • 示例:

    • main.js(由 Chunk 生成的 JavaScript 文件)。

    • main.css(由 CSS 模块提取生成的样式文件)。

    • main.js.map(Source Map 文件)。

  • stats中的数据结构:

assets 都会有一个共同的结构:

{
  "chunkNames": [], // 这个 asset 包含的 chunk
  "chunks": [ 10, 6 ], // 这个 asset 包含的 chunk 的 id
  "emitted": true, // 表示这个 asset 是否会让它输出到 output 目录
  "name": "10.web.js", // 输出的文件名
  "size": 1058 // 文件的大小
}

如下图:

assets-info

index.min.css 是 chunk index(编号0) 拆分出来的

index.bundle.js 也是 chunk index(编号0)拆分出来的

再次印证,同一个 chunk 可以产生多个 asset


三者之间的关系

  1. 模块(Modules) 是 Webpack 处理的最小单位,它们通过依赖关系组成依赖图。

  2. 代码块(Chunks) 是模块的分组,Webpack 根据入口点和代码分割策略将模块打包成 Chunk。

  3. 资源(Assets) 是 Chunk 经过处理后生成的最终文件,供浏览器加载和执行。

参考文档

https://www.webpackjs.com/api/stats/