[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow":1236,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow":1263},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":1232,"stem":1233,"id":1234,"extension":1235},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow","工作原理","Webpack 是静态模块打包器：从入口递归解析依赖，经 Loader 转换后输出一个或多个 bundle。与 Vite 对比见 Webpack 与 Vite。","技能小册",[12,13],"webpack","workflow","2025-12-19",false,{"type":17,"value":18,"toc":1221},"minimark",[19,22,48,51,56,59,70,207,221,225,232,237,358,362,595,599,663,679,683,687,725,729,776,782,837,853,857,861,906,910,975,984,988,997,1004,1036,1040,1058,1062,1091,1094,1097,1162,1165,1169,1172],[20,21,8],"h1",{"id":8},[23,24,25,32,33,37,38,42,43,47],"p",{},[26,27,31],"a",{"href":28,"rel":29},"https:\u002F\u002Fwebpack.js.org\u002F",[30],"nofollow","Webpack"," 是静态",[34,35,36],"strong",{},"模块打包器","：从入口递归解析依赖，经 Loader 转换后输出一个或多个 bundle。与 ",[26,39,41],{"href":40},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fworkflow","Vite"," 对比见 ",[26,44,46],{"href":45},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fproject\u002Fwebpack-vite","Webpack 与 Vite","。",[23,49,50],{},"下面从构建流程、Tapable、Module\u002FChunk、依赖图与 Runtime 五方面说明。",[52,53,55],"h3",{"id":54},"一完整构建流程","一、完整构建流程",[23,57,58],{},"Webpack 的构建过程可以概括为以下阶段：",[60,61,66],"pre",{"className":62,"code":64,"language":65},[63],"language-text","初始化参数 → 开始编译（创建 Compiler） → 确定入口 → 编译模块（递归查找依赖） → 构建模块（使用 Loader 转换） → 生成最终代码（Template + Chunk 优化） → 输出文件\n","text",[67,68,64],"code",{"__ignoreMap":69},"",[71,72,73,84,94,104,145,159,198],"ol",{},[74,75,76,79,80,83],"li",{},[34,77,78],{},"初始化参数","：读取 shell 命令或 ",[67,81,82],{},"webpack.config.js"," 配置，合并得到最终参数。",[74,85,86,89,90,93],{},[34,87,88],{},"创建 Compiler","：根据参数创建 ",[67,91,92],{},"Compiler"," 对象（核心调度器），并挂载所有内置插件和配置中的插件。",[74,95,96,99,100,103],{},[34,97,98],{},"确定入口","：从 ",[67,101,102],{},"entry"," 配置出发，解析入口文件的绝对路径。",[74,105,106,109,110,113,114],{},[34,107,108],{},"编译模块","（",[67,111,112],{},"make"," 阶段）：\n",[115,116,117,124,138],"ul",{},[74,118,119,120,123],{},"从入口开始，通过 ",[67,121,122],{},"acorn"," 等解析器将文件内容转换为 AST（抽象语法树）。",[74,125,126,127,130,131,130,134,137],{},"遍历 AST，收集 ",[67,128,129],{},"import","、",[67,132,133],{},"require",[67,135,136],{},"define"," 等依赖语句，记录依赖路径。",[74,139,140,141,144],{},"递归此过程，得到完整的模块依赖图（",[67,142,143],{},"Dependency Graph","）。",[74,146,147,150,151,154,155,158],{},[34,148,149],{},"构建模块","：对每个模块，根据其文件类型匹配配置中的 ",[67,152,153],{},"rules","，使用对应的 ",[34,156,157],{},"Loader"," 将源代码转换为 Webpack 可识别的 JavaScript 模块（例如将 SCSS 转 CSS，然后转成 JS 模块）。",[74,160,161,164,165],{},[34,162,163],{},"生成最终代码","：\n",[115,166,167,174,187],{},[74,168,169,170,173],{},"将所有模块组合成 ",[34,171,172],{},"Chunk","（根据入口和动态导入分割）。",[74,175,176,177,130,180,130,183,186],{},"应用优化（如 ",[67,178,179],{},"splitChunks",[67,181,182],{},"minimizer",[67,184,185],{},"sideEffects"," 过滤等）。",[74,188,189,190,193,194,197],{},"通过 ",[67,191,192],{},"Template"," 类生成最终 bundle 的代码串（包含 ",[67,195,196],{},"__webpack_require__"," 等运行时）。",[74,199,200,203,204,144],{},[34,201,202],{},"输出文件","：将生成的代码串写入到输出目录（",[67,205,206],{},"output.path",[23,208,209,210,212,213,216,217,220],{},"整个流程由 ",[67,211,92],{}," 和 ",[67,214,215],{},"Compilation"," 两个核心对象驱动，它们通过 ",[34,218,219],{},"Tapable"," 钩子机制在各个阶段暴露扩展点。",[52,222,224],{"id":223},"二tapable-事件流机制","二、Tapable 事件流机制",[23,226,227,228,231],{},"Tapable 是 Webpack 内部实现的一个小型发布-订阅库，定义了多种钩子类型，插件可以通过 ",[67,229,230],{},"tap\u002FtapAsync\u002FtapPromise"," 注册回调，在特定时机被执行。",[233,234,236],"h4",{"id":235},"_1-核心钩子类型","1. 核心钩子类型",[238,239,240,256],"table",{},[241,242,243],"thead",{},[244,245,246,250,253],"tr",{},[247,248,249],"th",{},"类型",[247,251,252],{},"执行模式",[247,254,255],{},"典型应用场景",[257,258,259,277,294,310,325,342],"tbody",{},[244,260,261,267,270],{},[262,263,264],"td",{},[67,265,266],{},"SyncHook",[262,268,269],{},"同步顺序执行，不关心返回值",[262,271,272,273,276],{},"普通广播，如 ",[67,274,275],{},"compilation"," 结束",[244,278,279,284,291],{},[262,280,281],{},[67,282,283],{},"SyncBailHook",[262,285,286,287,290],{},"同步执行，任一回调返回非 ",[67,288,289],{},"undefined"," 则停止",[262,292,293],{},"校验类，如某个 loader 返回结果",[244,295,296,301,304],{},[262,297,298],{},[67,299,300],{},"SyncWaterfallHook",[262,302,303],{},"同步执行，上一个返回值作为下一个参数",[262,305,306,307],{},"链式转换，如 ",[67,308,309],{},"normalModuleLoader",[244,311,312,317,322],{},[262,313,314],{},[67,315,316],{},"SyncLoopHook",[262,318,319,320],{},"循环执行直到所有回调返回 ",[67,321,289],{},[262,323,324],{},"较少用",[244,326,327,332,339],{},[262,328,329],{},[67,330,331],{},"AsyncParallelHook",[262,333,334,335,338],{},"异步并行执行（通过 ",[67,336,337],{},"tapAsync\u002FtapPromise","）",[262,340,341],{},"多个独立任务，如多个 Loader 编译",[244,343,344,349,352],{},[262,345,346],{},[67,347,348],{},"AsyncSeriesHook",[262,350,351],{},"异步串行执行（一个完成后执行下一个）",[262,353,354,355,357],{},"递归构建模块，如 ",[67,356,112],{}," 阶段",[233,359,361],{"id":360},"_2-关键钩子触发时机compiler-compilation","2. 关键钩子触发时机（Compiler \u002F Compilation）",[238,363,364,377],{},[241,365,366],{},[244,367,368,371,374],{},[247,369,370],{},"钩子名",[247,372,373],{},"触发时机",[247,375,376],{},"常用插件示例",[257,378,379,399,415,434,450,470,488,501,514,527,540,556,569,582],{},[244,380,381,390,396],{},[262,382,383,386,387],{},[67,384,385],{},"environment"," \u002F ",[67,388,389],{},"afterEnvironment",[262,391,392,393,395],{},"读取配置完成后，创建 ",[67,394,92],{}," 前",[262,397,398],{},"设置环境变量",[244,400,401,406,412],{},[262,402,403],{},[67,404,405],{},"entryOption",[262,407,408,409,411],{},"解析 ",[67,410,102],{}," 配置后",[262,413,414],{},"动态修改入口",[244,416,417,425,431],{},[262,418,419,386,422],{},[67,420,421],{},"beforeRun",[67,423,424],{},"run",[262,426,427,430],{},[67,428,429],{},"compiler.run()"," 开始前\u002F后",[262,432,433],{},"清理输出目录插件",[244,435,436,441,447],{},[262,437,438],{},[67,439,440],{},"compile",[262,442,443,444,446],{},"创建新 ",[67,445,215],{}," 对象之前",[262,448,449],{},"准备钩子",[244,451,452,456,464],{},[262,453,454],{},[67,455,275],{},[262,457,458,459,461,462,338],{},"创建 ",[67,460,215],{}," 对象后（参数为 ",[67,463,275],{},[262,465,466,467,469],{},"注册插件到 ",[67,468,275],{}," 的钩子",[244,471,472,476,479],{},[262,473,474],{},[67,475,112],{},[262,477,478],{},"开始构建依赖图（递归编译模块）",[262,480,481,484,485],{},[34,482,483],{},"核心构建钩子","，如 ",[67,486,487],{},"SingleEntryPlugin",[244,489,490,495,498],{},[262,491,492],{},[67,493,494],{},"buildModule",[262,496,497],{},"单个模块开始构建前",[262,499,500],{},"自定义 Loader 行为",[244,502,503,508,511],{},[262,504,505],{},[67,506,507],{},"succeedModule",[262,509,510],{},"模块构建成功",[262,512,513],{},"统计模块信息",[244,515,516,521,524],{},[262,517,518],{},[67,519,520],{},"finishModules",[262,522,523],{},"所有模块构建完成",[262,525,526],{},"分析依赖关系",[244,528,529,534,537],{},[262,530,531],{},[67,532,533],{},"seal",[262,535,536],{},"停止接收新模块，开始优化和生成 Chunk",[262,538,539],{},"生成 Chunk 逻辑",[244,541,542,547,553],{},[262,543,544],{},[67,545,546],{},"optimizeChunks",[262,548,549,550,552],{},"Chunk 优化阶段（",[67,551,179],{}," 在此生效）",[262,554,555],{},"分割代码块",[244,557,558,563,566],{},[262,559,560],{},[67,561,562],{},"emit",[262,564,565],{},"生成资源到输出目录前（可修改资源内容）",[262,567,568],{},"内联资源、上传 CDN",[244,570,571,576,579],{},[262,572,573],{},[67,574,575],{},"afterEmit",[262,577,578],{},"输出完成后",[262,580,581],{},"清理临时文件",[244,583,584,589,592],{},[262,585,586],{},[67,587,588],{},"done",[262,590,591],{},"整个打包完成",[262,593,594],{},"构建完成通知",[233,596,598],{"id":597},"_3-手写插件时如何选择钩子","3. 手写插件时如何选择钩子",[115,600,601,613,623,635,652],{},[74,602,603,606,607,610,611,47],{},[34,604,605],{},"需要修改模块内容","：使用 ",[67,608,609],{},"compilation.hooks.buildModule"," 或 ",[67,612,309],{},[74,614,615,606,618,610,621,47],{},[34,616,617],{},"需要添加额外资源",[67,619,620],{},"compilation.hooks.additionalAssets",[67,622,562],{},[74,624,625,606,628,610,631,634],{},[34,626,627],{},"需要改变依赖解析",[67,629,630],{},"compilation.hooks.resolve",[67,632,633],{},"normalModuleFactory"," 钩子。",[74,636,637,640,641,643,644,646,647,130,649,144],{},[34,638,639],{},"需要影响打包结果","：在 ",[67,642,533],{}," 之后到 ",[67,645,562],{}," 之前的钩子（如 ",[67,648,546],{},[67,650,651],{},"optimizeModules",[74,653,654,657,658,610,660,662],{},[34,655,656],{},"写一个简单日志插件","：",[67,659,588],{},[67,661,440],{}," 即可。",[23,664,665,668,669,386,672,386,675,678],{},[34,666,667],{},"注意","：钩子有同步\u002F异步之分，注册时需使用对应的 ",[67,670,671],{},"tap",[67,673,674],{},"tapAsync",[67,676,677],{},"tapPromise","，且需要知道钩子预期接收的参数签名（参考 Webpack 文档）。",[52,680,682],{"id":681},"三module-与-chunk-的关系","三、Module 与 Chunk 的关系",[233,684,686],{"id":685},"_1-module模块","1. Module（模块）",[115,688,689,692,712],{},[74,690,691],{},"代表文件级别的独立单元。",[74,693,694,695,130,698,130,701,130,704,707,708,711],{},"每个源文件（",[67,696,697],{},".js",[67,699,700],{},".css",[67,702,703],{},".png",[67,705,706],{},".vue"," 等）经过 Loader 处理后，都会变成一个 ",[67,709,710],{},"Module"," 对象。",[74,713,714,716,717,720,721,724],{},[67,715,710],{}," 中存储了：文件路径、依赖列表（",[67,718,719],{},"dependencies","）、原始内容、转换后的代码、",[67,722,723],{},"hash"," 等信息。",[233,726,728],{"id":727},"_2-chunk代码块","2. Chunk（代码块）",[115,730,731,737],{},[74,732,733,734,736],{},"一个或多个 ",[67,735,710],{}," 的集合，最终输出为一个文件（bundle）。",[74,738,739,740],{},"分类：\n",[115,741,742,748,757,767],{},[74,743,744,747],{},[34,745,746],{},"Entry Chunk","：入口文件及其依赖形成的 chunk。",[74,749,750,753,754,756],{},[34,751,752],{},"Runtime Chunk","：包含 ",[67,755,196],{}," 等引导代码的 chunk。",[74,758,759,762,763,766],{},[34,760,761],{},"Async Chunk","：通过 ",[67,764,765],{},"import()"," 动态导入产生的 chunk。",[74,768,769,99,772,775],{},[34,770,771],{},"Vendor Chunk",[67,773,774],{},"node_modules"," 中抽取的第三方库。",[233,777,779,780],{"id":778},"_3-chunk-graph-的生成与-splitchunks","3. Chunk Graph 的生成与 ",[67,781,179],{},[71,783,784,792,802],{},[74,785,786,789,790,47],{},[34,787,788],{},"初始阶段","：每个入口模块及其同步依赖形成一个初始 ",[67,791,746],{},[74,793,794,657,797,799,800,47],{},[34,795,796],{},"动态导入",[67,798,765],{}," 会创建一个新的 ",[67,801,761],{},[74,803,804,164,810],{},[34,805,806,807,338],{},"优化阶段（",[67,808,809],{},"optimization.splitChunks",[115,811,812,815,821,834],{},[74,813,814],{},"Webpack 会分析所有 Chunk 之间的模块重叠情况。",[74,816,189,817,820],{},[67,818,819],{},"SplitChunksPlugin"," 提取公共模块（例如被多个入口\u002F异步 chunk 引用的 lodash、vue 等）。",[74,822,823,824,130,827,130,830,833],{},"内部算法基于",[34,825,826],{},"模块被引用次数",[34,828,829],{},"chunk 数量阈值",[34,831,832],{},"模块体积阈值","等参数，决定是否提取为新 chunk。",[74,835,836],{},"提取后，原 chunk 中对公共模块的引用会被替换为对提取出的 chunk 的引用。",[23,838,839,657,842,844,845,848,849,852],{},[34,840,841],{},"核心原理",[67,843,819],{}," 会生成一个新的 ",[67,846,847],{},"ChunkGroup","，将公共模块移入，然后调整依赖关系。这是通过 ",[67,850,851],{},"compilation.hooks.optimizeChunks"," 钩子完成的。",[52,854,856],{"id":855},"四依赖图谱dependency-graph","四、依赖图谱（Dependency Graph）",[233,858,860],{"id":859},"_1-模块引用关系的建立","1. 模块引用关系的建立",[115,862,863,873,886,893,903],{},[74,864,865,866,868,869,872],{},"当 Webpack 读取一个模块文件时，会使用 ",[67,867,122],{},"（或 ",[67,870,871],{},"@babel\u002Fparser","）将代码解析为 AST。",[74,874,875,876,130,878,130,881,130,883,885],{},"遍历 AST，识别所有 ",[67,877,129],{},[67,879,880],{},"export",[67,882,133],{},[67,884,136],{}," 等语句。",[74,887,888,889,892],{},"对于每个依赖，记录其请求路径（request），并通过 ",[67,890,891],{},"resolve"," 机制将其转换为绝对路径。",[74,894,895,896,899,900,902],{},"创建一个 ",[67,897,898],{},"Dependency"," 对象，并添加到当前模块的 ",[67,901,719],{}," 列表中。",[74,904,905],{},"递归处理每个新找到的模块，直到所有模块都被访问。",[233,907,909],{"id":908},"_2-tree-shaking-的标记机制","2. Tree Shaking 的标记机制",[115,911,912,941],{},[74,913,914,917,918,921,922,925,926],{},[34,915,916],{},"usedExports","：Webpack 在打包时，通过 ",[67,919,920],{},"optimization.usedExports"," 开启后，会利用 ",[34,923,924],{},"terser"," 等优化工具分析代码中哪些导出被使用了。\n",[115,927,928,934],{},[74,929,930,931,933],{},"对于 ESM 的 ",[67,932,880],{},"，Webpack 会在模块构建时记录导出名称。",[74,935,936,937,940],{},"在生成最终代码时，只保留被引用的导出，未使用的导出会被标记为 ",[67,938,939],{},"\u002F* unused *\u002F","，最后由压缩工具删除。",[74,942,943,164,945],{},[34,944,185],{},[115,946,947,958,968],{},[74,948,949,950,953,954,957],{},"通过在 ",[67,951,952],{},"package.json"," 中声明 ",[67,955,956],{},"\"sideEffects\": false","，告知 Webpack 该包的所有模块都没有副作用（即仅导入但不使用时可安全删除）。",[74,959,960,961,964,965,47],{},"如果模块有副作用（如 ",[67,962,963],{},"import '.\u002Fpolyfill'","），则需标记 ",[67,966,967],{},"\"sideEffects\": [\".\u002Fpolyfill.js\"]",[74,969,970,971,974],{},"Webpack 在分析时，如果遇到 ",[67,972,973],{},"sideEffects: false"," 的包，且仅引用了其中未使用的导出，则会完全跳过该模块的打包。",[23,976,977,978,980,981,983],{},"两者协作：",[67,979,185],{}," 控制模块级删除，",[67,982,916],{}," 控制模块内部导出级删除。",[52,985,987],{"id":986},"五runtime-代码注入","五、Runtime 代码注入",[23,989,990,991,993,994,47],{},"Webpack 生成的 bundle 中除了模块代码外，还包含一套用于浏览器端加载、执行模块的运行时（Runtime）。核心包括 ",[67,992,196],{}," 函数和 ",[67,995,996],{},"manifest",[233,998,1000,1001,1003],{"id":999},"_1-__webpack_require__-模块加载函数","1. ",[67,1002,196],{}," 模块加载函数",[115,1005,1006,1016,1023,1029],{},[74,1007,1008,1009,1012,1013,144],{},"它维护一个 ",[67,1010,1011],{},"installedModules"," 缓存对象（",[67,1014,1015],{},"moduleId -> exports",[74,1017,1018,1019,1022],{},"接受 ",[67,1020,1021],{},"moduleId","，如果缓存中存在则直接返回；否则创建一个新模块对象，执行模块函数，并缓存。",[74,1024,1025,1026,1028],{},"模块函数的代码中会调用 ",[67,1027,196],{}," 来引入依赖。",[74,1030,1031,1032,1035],{},"支持动态导入：",[67,1033,1034],{},"__webpack_require__.e"," 用于加载异步 chunk。",[233,1037,1039],{"id":1038},"_2-manifest清单","2. Manifest（清单）",[115,1041,1042,1045,1051],{},[74,1043,1044],{},"Manifest 是一个记录所有模块 ID 到其对应 chunk 文件路径（或 chunk ID）的映射表。",[74,1046,1047,1048,1050],{},"它帮助 ",[67,1049,196],{}," 在运行时找到异步 chunk 的 URL。",[74,1052,1053,1054,1057],{},"Manifest 可以单独提取为一个文件（通过 ",[67,1055,1056],{},"optimization.runtimeChunk: true","），以便于缓存控制。",[233,1059,1061],{"id":1060},"_3-其他辅助函数","3. 其他辅助函数",[115,1063,1064,1070,1079,1085],{},[74,1065,1066,1069],{},[67,1067,1068],{},"__webpack_require__.d","：定义 getter 使导出可被外部访问。",[74,1071,1072,657,1075,1078],{},[67,1073,1074],{},"__webpack_require__.o",[67,1076,1077],{},"hasOwnProperty"," 简写。",[74,1080,1081,1084],{},[67,1082,1083],{},"__webpack_require__.r","：标记模块为 ES 模块。",[74,1086,1087,1090],{},[67,1088,1089],{},"__webpack_require__.n","：兼容 CommonJS 模块的 default 导出。",[23,1092,1093],{},"这些函数被包裹在立即执行函数（IIFE）中，构成最终的 bundle。",[52,1095,1096],{"id":1096},"总结",[238,1098,1099,1109],{},[241,1100,1101],{},[244,1102,1103,1106],{},[247,1104,1105],{},"概念",[247,1107,1108],{},"作用",[257,1110,1111,1121,1130,1140,1150],{},[244,1112,1113,1118],{},[262,1114,1115],{},[34,1116,1117],{},"构建流程",[262,1119,1120],{},"配置初始化 → 创建 Compiler → 递归构建模块 → 生成 Chunk → 输出",[244,1122,1123,1127],{},[262,1124,1125],{},[34,1126,219],{},[262,1128,1129],{},"提供插件钩子系统，控制整个构建生命周期的扩展点",[244,1131,1132,1137],{},[262,1133,1134],{},[34,1135,1136],{},"Module\u002FChunk",[262,1138,1139],{},"Module 是源文件单元，Chunk 是输出单元；splitChunks 利用引用计数拆分",[244,1141,1142,1147],{},[262,1143,1144],{},[34,1145,1146],{},"依赖图谱",[262,1148,1149],{},"AST 解析建立依赖关系；Tree Shaking 依赖 usedExports + sideEffects 标记删除",[244,1151,1152,1157],{},[262,1153,1154],{},[34,1155,1156],{},"Runtime",[262,1158,1159,1161],{},[67,1160,196],{}," + manifest 提供浏览器端模块加载能力",[23,1163,1164],{},"理解这些原理，可以帮助我们更好地配置 Webpack、编写自定义插件，以及诊断打包问题。",[1166,1167,1168],"h2",{"id":1168},"参考文献",[23,1170,1171],{},"以下链接在编写时均可正常访问：",[238,1173,1174,1184],{},[241,1175,1176],{},[244,1177,1178,1181],{},[247,1179,1180],{},"资料",[247,1182,1183],{},"说明",[257,1185,1186,1198,1209],{},[244,1187,1188,1195],{},[262,1189,1190],{},[26,1191,1194],{"href":1192,"rel":1193},"https:\u002F\u002Fwebpack.js.org\u002Fconcepts\u002F",[30],"Webpack 概念",[262,1196,1197],{},"官方",[244,1199,1200,1206],{},[262,1201,1202],{},[26,1203,219],{"href":1204,"rel":1205},"https:\u002F\u002Fgithub.com\u002Fwebpack\u002Ftapable",[30],[262,1207,1208],{},"钩子库",[244,1210,1211,1218],{},[262,1212,1213],{},[26,1214,1217],{"href":1215,"rel":1216},"https:\u002F\u002Fwebpack.js.org\u002Fapi\u002Fcompiler-hooks\u002F",[30],"编译器钩子",[262,1219,1220],{},"插件扩展",{"title":69,"searchDepth":1222,"depth":1222,"links":1223},2,[1224,1226,1227,1228,1229,1230,1231],{"id":54,"depth":1225,"text":55},3,{"id":223,"depth":1225,"text":224},{"id":681,"depth":1225,"text":682},{"id":855,"depth":1225,"text":856},{"id":986,"depth":1225,"text":987},{"id":1096,"depth":1225,"text":1096},{"id":1168,"depth":1222,"text":1168},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fworkflow","knowledge\u002Fknowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fworkflow.md","md",{"items":1237},[1238,1243,1247,1250,1254,1258],{"path":1239,"title":1240,"description":1241,"category":10,"score":1242},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks","产物优化","Webpack 通过代码分割、Tree Shaking、压缩与资源模块等减少体积、改善缓存。原理背景见 工作原理。",6,{"path":1244,"title":1245,"description":1246,"category":10,"score":1242},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fcompany","企业级实践","大型前端项目在 Webpack 场景下的多环境拆分、Docker 构建缓存、自定义 CLI 与微前端（Module Federation \u002F single-spa）等实践。入门见 工程化概览。",{"path":1248,"title":157,"description":1249,"category":10,"score":1242},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader","Loader 在 Webpack 构建链中把源文件转为可打包的 JS 模块（如 TS、SCSS、Vue SFC）。见 工作原理。",{"path":1251,"title":1252,"description":1253,"category":10,"score":1242},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fadvanced","进阶配置","Webpack 进阶场景：多页面（MPA）、devServer、环境变量注入、Source Map、Module Federation 等。基础见 工作原理。",{"path":1255,"title":1256,"description":1257,"category":10,"score":1242},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin","Plugin","Webpack 插件在构建生命周期钩子上扩展能力（修改资源、生成 HTML、上传 CDN 等）。背景见 工作原理；与 Loader 分工：Loader 转换单文件，插件面向整体构建。",{"path":1259,"title":1260,"description":1261,"category":10,"score":1262},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fproject\u002Fother","其他配置","除 ESLint、Prettier 等规范文件外，仓库中常见的工具链与包管理配置如下。见 工程化概览。",4,{"series":1264,"title":12,"items":1265,"index":1277,"prev":1278,"next":1279},"booklet\u002Fproject\u002Fwebpack",[1266,1268,1270,1272,1274,1276],{"path":1251,"title":1252,"date":1267,"pinned":15},"2021-10-18",{"path":1239,"title":1240,"date":1269,"pinned":15},"2025-01-28",{"path":1244,"title":1245,"date":1271,"pinned":15},"2024-07-30",{"path":1248,"title":157,"date":1273,"pinned":15},"2022-11-14",{"path":1255,"title":1256,"date":1275,"pinned":15},"2020-08-27",{"path":7,"title":8,"date":14,"pinned":15},5,{"path":1255,"title":1256,"date":1275,"pinned":15},null]