Webpack stats 详解(图文+注释)
介绍
通过 webpack 编译源文件时,用户可以生成包含有关于模块的统计数据的 JSON 文件。这些统计数据不仅可以帮助开发者来分析应用的依赖图表,还可以优化编译的速度。
这个 JSON 文件可以通过以下的命令来生成:
npx webpack --json > stats.json
# 指定config
npx webpack --config config.js --json > stats.json
详情
打开 stats.json,其文件目录如下
从文件中可以看出如下信息
字段名 | 说明 |
---|---|
version | Webpack 的版本号。 |
hash | 构建的唯一哈希值,用于标识此次构建。 |
time | 构建耗时,单位为毫秒。 |
builtAt | 构建完成的时间戳。 |
publicPath | 输出文件的公共路径。 |
outputPath | 输出文件的目录路径。 |
assets | 构建生成的文件列表,包含文件名、大小等信息。 |
entrypoints | 入口点及其对应的资源文件。 |
chunks | 生成的代码块信息,包括名称、大小、包含的模块等。 |
modules | 所有模块的详细信息,如路径、大小、依赖等。 |
errors | 构建过程中的错误信息。 |
warnings | 构建过程中的警告信息。 |
children | 子编译过程的 stats 信息,常用于多配置构建。 |
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`的数组
]
}
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 // 文件的大小
}
如下图:
index.min.css 是 chunk index(编号0) 拆分出来的
index.bundle.js 也是 chunk index(编号0)拆分出来的
再次印证,同一个 chunk 可以产生多个 asset
三者之间的关系
模块(Modules) 是 Webpack 处理的最小单位,它们通过依赖关系组成依赖图。
代码块(Chunks) 是模块的分组,Webpack 根据入口点和代码分割策略将模块打包成 Chunk。
资源(Assets) 是 Chunk 经过处理后生成的最终文件,供浏览器加载和执行。