[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks":2187,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks":2211},{"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":2183,"stem":2184,"id":2185,"extension":2186},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks","产物优化","Webpack 通过代码分割、Tree Shaking、压缩与资源模块等减少体积、改善缓存。原理背景见 工作原理。","技能小册",[12,13],"webpack","chunks","2025-01-28",false,{"type":17,"value":18,"toc":2175},"minimark",[19,22,32,37,40,50,347,399,406,507,522,534,565,636,644,740,757,761,771,778,789,842,849,886,890,901,968,971,975,996,1050,1058,1076,1118,1121,1133,1137,1144,1147,1385,1423,1430,1436,1609,1616,1620,1632,1636,1708,1712,1854,1859,1867,1873,1924,1936,1947,1955,1979,1987,2011,2025,2031,2034,2038,2114,2117,2120,2123,2171],[20,21,8],"h1",{"id":8},[23,24,25,26,31],"p",{},"Webpack 通过代码分割、Tree Shaking、压缩与资源模块等减少体积、改善缓存。原理背景见 ",[27,28,30],"a",{"href":29},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow","工作原理","。",[33,34,36],"h3",{"id":35},"一代码分割split-chunks","一、代码分割（Split Chunks）",[23,38,39],{},"代码分割的目的是避免重复依赖，将公共代码提取为独立 chunk，充分利用浏览器缓存。",[41,42,44,45,49],"h4",{"id":43},"_1-splitchunksplugin-核心策略","1. ",[46,47,48],"code",{},"SplitChunksPlugin"," 核心策略",[51,52,57],"pre",{"className":53,"code":54,"language":55,"meta":56,"style":56},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F webpack.config.js\noptimization: {\n  splitChunks: {\n    chunks: 'all',          \u002F\u002F 对同步和异步模块都进行分割\n    minSize: 20000,        \u002F\u002F 模块大于 20KB 才单独打包（避免过小 chunk）\n    maxSize: 0,            \u002F\u002F 不限制最大体积（可设置如 50000）\n    cacheGroups: {         \u002F\u002F 分组策略\n      vendor: {\n        test: \u002F[\\\\\u002F]node_modules[\\\\\u002F]\u002F,\n        name: 'vendors',\n        chunks: 'all',\n        priority: 10,      \u002F\u002F 优先级高于默认组\n      },\n      common: {\n        minChunks: 2,      \u002F\u002F 至少被 2 个 chunk 引用的公共模块\n        priority: 5,\n        reuseExistingChunk: true,\n      },\n    },\n  },\n}\n","js","",[46,58,59,68,82,92,117,134,150,164,174,217,234,250,266,272,282,298,310,324,329,335,341],{"__ignoreMap":56},[60,61,64],"span",{"class":62,"line":63},"line",1,[60,65,67],{"class":66},"sutJx","\u002F\u002F webpack.config.js\n",[60,69,71,75,79],{"class":62,"line":70},2,[60,72,74],{"class":73},"sbgvK","optimization",[60,76,78],{"class":77},"sP7_E",":",[60,80,81],{"class":77}," {\n",[60,83,85,88,90],{"class":62,"line":84},3,[60,86,87],{"class":73},"  splitChunks",[60,89,78],{"class":77},[60,91,81],{"class":77},[60,93,95,98,100,104,108,111,114],{"class":62,"line":94},4,[60,96,97],{"class":73},"    chunks",[60,99,78],{"class":77},[60,101,103],{"class":102},"sjJ54"," '",[60,105,107],{"class":106},"s_sjI","all",[60,109,110],{"class":102},"'",[60,112,113],{"class":77},",",[60,115,116],{"class":66},"          \u002F\u002F 对同步和异步模块都进行分割\n",[60,118,120,123,125,129,131],{"class":62,"line":119},5,[60,121,122],{"class":73},"    minSize",[60,124,78],{"class":77},[60,126,128],{"class":127},"srdBf"," 20000",[60,130,113],{"class":77},[60,132,133],{"class":66},"        \u002F\u002F 模块大于 20KB 才单独打包（避免过小 chunk）\n",[60,135,137,140,142,145,147],{"class":62,"line":136},6,[60,138,139],{"class":73},"    maxSize",[60,141,78],{"class":77},[60,143,144],{"class":127}," 0",[60,146,113],{"class":77},[60,148,149],{"class":66},"            \u002F\u002F 不限制最大体积（可设置如 50000）\n",[60,151,153,156,158,161],{"class":62,"line":152},7,[60,154,155],{"class":73},"    cacheGroups",[60,157,78],{"class":77},[60,159,160],{"class":77}," {",[60,162,163],{"class":66},"         \u002F\u002F 分组策略\n",[60,165,167,170,172],{"class":62,"line":166},8,[60,168,169],{"class":73},"      vendor",[60,171,78],{"class":77},[60,173,81],{"class":77},[60,175,177,180,182,185,189,193,197,200,204,206,208,210,212,214],{"class":62,"line":176},9,[60,178,179],{"class":73},"        test",[60,181,78],{"class":77},[60,183,184],{"class":102}," \u002F",[60,186,188],{"class":187},"s39Yj","[",[60,190,192],{"class":191},"sjYin","\\\\",[60,194,196],{"class":195},"stzsN","\u002F",[60,198,199],{"class":187},"]",[60,201,203],{"class":202},"sQRbd","node_modules",[60,205,188],{"class":187},[60,207,192],{"class":191},[60,209,196],{"class":195},[60,211,199],{"class":187},[60,213,196],{"class":102},[60,215,216],{"class":77},",\n",[60,218,220,223,225,227,230,232],{"class":62,"line":219},10,[60,221,222],{"class":73},"        name",[60,224,78],{"class":77},[60,226,103],{"class":102},[60,228,229],{"class":106},"vendors",[60,231,110],{"class":102},[60,233,216],{"class":77},[60,235,237,240,242,244,246,248],{"class":62,"line":236},11,[60,238,239],{"class":73},"        chunks",[60,241,78],{"class":77},[60,243,103],{"class":102},[60,245,107],{"class":106},[60,247,110],{"class":102},[60,249,216],{"class":77},[60,251,253,256,258,261,263],{"class":62,"line":252},12,[60,254,255],{"class":73},"        priority",[60,257,78],{"class":77},[60,259,260],{"class":127}," 10",[60,262,113],{"class":77},[60,264,265],{"class":66},"      \u002F\u002F 优先级高于默认组\n",[60,267,269],{"class":62,"line":268},13,[60,270,271],{"class":77},"      },\n",[60,273,275,278,280],{"class":62,"line":274},14,[60,276,277],{"class":73},"      common",[60,279,78],{"class":77},[60,281,81],{"class":77},[60,283,285,288,290,293,295],{"class":62,"line":284},15,[60,286,287],{"class":73},"        minChunks",[60,289,78],{"class":77},[60,291,292],{"class":127}," 2",[60,294,113],{"class":77},[60,296,297],{"class":66},"      \u002F\u002F 至少被 2 个 chunk 引用的公共模块\n",[60,299,301,303,305,308],{"class":62,"line":300},16,[60,302,255],{"class":73},[60,304,78],{"class":77},[60,306,307],{"class":127}," 5",[60,309,216],{"class":77},[60,311,313,316,318,322],{"class":62,"line":312},17,[60,314,315],{"class":73},"        reuseExistingChunk",[60,317,78],{"class":77},[60,319,321],{"class":320},"syTEX"," true",[60,323,216],{"class":77},[60,325,327],{"class":62,"line":326},18,[60,328,271],{"class":77},[60,330,332],{"class":62,"line":331},19,[60,333,334],{"class":77},"    },\n",[60,336,338],{"class":62,"line":337},20,[60,339,340],{"class":77},"  },\n",[60,342,344],{"class":62,"line":343},21,[60,345,346],{"class":77},"}\n",[348,349,350,364,372,380],"ul",{},[351,352,353,359,360,363],"li",{},[354,355,356],"strong",{},[46,357,358],{},"chunks: 'all'","：同时分割同步和异步模块，推荐使用。若设为 ",[46,361,362],{},"'async'"," 仅分割动态导入模块。",[351,365,366,371],{},[354,367,368],{},[46,369,370],{},"minSize","：模块体积小于该值的不会单独拆分成 chunk，避免请求过多。",[351,373,374,379],{},[354,375,376],{},[46,377,378],{},"maxSize","：尝试将大于该值的 chunk 拆分成多个小 chunk，提高缓存命中率（谨慎使用，可能导致请求增多）。",[351,381,382,387,388,391,392,391,395,398],{},[354,383,384],{},[46,385,386],{},"cacheGroups","：定义提取策略，可以自定义多个分组（如 ",[46,389,390],{},"vendor","、",[46,393,394],{},"common",[46,396,397],{},"styles"," 等）。",[41,400,402,403,405],{"id":401},"_2-将-node_modules-拆分为单独的-vendor-chunk避免重复依赖","2. 将 ",[46,404,203],{}," 拆分为单独的 vendor chunk，避免重复依赖",[51,407,409],{"className":53,"code":408,"language":55,"meta":56,"style":56},"cacheGroups: {\n  vendor: {\n    test: \u002F[\\\\\u002F]node_modules[\\\\\u002F]\u002F,\n    name: 'vendors',\n    chunks: 'all',\n    priority: 10,\n  },\n}\n",[46,410,411,419,428,459,474,488,499,503],{"__ignoreMap":56},[60,412,413,415,417],{"class":62,"line":63},[60,414,386],{"class":73},[60,416,78],{"class":77},[60,418,81],{"class":77},[60,420,421,424,426],{"class":62,"line":70},[60,422,423],{"class":73},"  vendor",[60,425,78],{"class":77},[60,427,81],{"class":77},[60,429,430,433,435,437,439,441,443,445,447,449,451,453,455,457],{"class":62,"line":84},[60,431,432],{"class":73},"    test",[60,434,78],{"class":77},[60,436,184],{"class":102},[60,438,188],{"class":187},[60,440,192],{"class":191},[60,442,196],{"class":195},[60,444,199],{"class":187},[60,446,203],{"class":202},[60,448,188],{"class":187},[60,450,192],{"class":191},[60,452,196],{"class":195},[60,454,199],{"class":187},[60,456,196],{"class":102},[60,458,216],{"class":77},[60,460,461,464,466,468,470,472],{"class":62,"line":94},[60,462,463],{"class":73},"    name",[60,465,78],{"class":77},[60,467,103],{"class":102},[60,469,229],{"class":106},[60,471,110],{"class":102},[60,473,216],{"class":77},[60,475,476,478,480,482,484,486],{"class":62,"line":119},[60,477,97],{"class":73},[60,479,78],{"class":77},[60,481,103],{"class":102},[60,483,107],{"class":106},[60,485,110],{"class":102},[60,487,216],{"class":77},[60,489,490,493,495,497],{"class":62,"line":136},[60,491,492],{"class":73},"    priority",[60,494,78],{"class":77},[60,496,260],{"class":127},[60,498,216],{"class":77},[60,500,501],{"class":62,"line":152},[60,502,340],{"class":77},[60,504,505],{"class":62,"line":166},[60,506,346],{"class":77},[348,508,509,519],{},[351,510,511,512,514,515,518],{},"原理：所有来自 ",[46,513,203],{}," 的模块会被合并到 ",[46,516,517],{},"vendors.js"," 中。",[351,520,521],{},"如果多个入口或异步 chunk 引用了相同的第三方库，此配置可避免重复打包。",[41,523,525,526,529,530,533],{"id":524},"_3-priority-和-reuseexistingchunk-实战","3. ",[46,527,528],{},"priority"," 和 ",[46,531,532],{},"reuseExistingChunk"," 实战",[348,535,536,558],{},[351,537,538,542,543,545,546,549,550,553,554,557],{},[354,539,540],{},[46,541,528],{},"：数值越大，该分组越优先匹配。例如 ",[46,544,390],{}," 的 ",[46,547,548],{},"priority: 10"," 会优先于默认 ",[46,551,552],{},"default"," 组的 ",[46,555,556],{},"priority: 0","，防止公共模块被错误地归入普通 chunk。",[351,559,560,564],{},[354,561,562],{},[46,563,532],{},"：如果当前 chunk 包含的模块已在之前的 chunk 中存在，则直接复用，不再重复打包。减少冗余代码。",[51,566,568],{"className":53,"code":567,"language":55,"meta":56,"style":56},"cacheGroups: {\n  default: {\n    minChunks: 2,\n    priority: -20,\n    reuseExistingChunk: true,\n  },\n}\n",[46,569,570,578,591,602,617,628,632],{"__ignoreMap":56},[60,571,572,574,576],{"class":62,"line":63},[60,573,386],{"class":73},[60,575,78],{"class":77},[60,577,81],{"class":77},[60,579,580,584,588],{"class":62,"line":70},[60,581,583],{"class":582},"sVHd0","  default",[60,585,587],{"class":586},"skxfh",": ",[60,589,590],{"class":77},"{\n",[60,592,593,596,598,600],{"class":62,"line":84},[60,594,595],{"class":586},"    minChunks",[60,597,78],{"class":77},[60,599,292],{"class":127},[60,601,216],{"class":77},[60,603,604,606,608,612,615],{"class":62,"line":94},[60,605,492],{"class":586},[60,607,78],{"class":77},[60,609,611],{"class":610},"smGrS"," -",[60,613,614],{"class":127},"20",[60,616,216],{"class":77},[60,618,619,622,624,626],{"class":62,"line":119},[60,620,621],{"class":586},"    reuseExistingChunk",[60,623,78],{"class":77},[60,625,321],{"class":320},[60,627,216],{"class":77},[60,629,630],{"class":62,"line":136},[60,631,340],{"class":77},[60,633,634],{"class":62,"line":152},[60,635,346],{"class":77},[41,637,639,640,643],{"id":638},"_4-将多个异步-chunk-中公共的小模块进一步提取minchunks-配置","4. 将多个异步 chunk 中公共的小模块进一步提取（",[46,641,642],{},"minChunks"," 配置）",[51,645,647],{"className":53,"code":646,"language":55,"meta":56,"style":56},"cacheGroups: {\n  commons: {\n    chunks: 'async',        \u002F\u002F 只对异步 chunk 生效\n    minChunks: 2,           \u002F\u002F 至少被 2 个异步 chunk 共用\n    name: 'common-async',\n    priority: 5,\n    reuseExistingChunk: true,\n  },\n}\n",[46,648,649,657,666,684,697,712,722,732,736],{"__ignoreMap":56},[60,650,651,653,655],{"class":62,"line":63},[60,652,386],{"class":73},[60,654,78],{"class":77},[60,656,81],{"class":77},[60,658,659,662,664],{"class":62,"line":70},[60,660,661],{"class":73},"  commons",[60,663,78],{"class":77},[60,665,81],{"class":77},[60,667,668,670,672,674,677,679,681],{"class":62,"line":84},[60,669,97],{"class":73},[60,671,78],{"class":77},[60,673,103],{"class":102},[60,675,676],{"class":106},"async",[60,678,110],{"class":102},[60,680,113],{"class":77},[60,682,683],{"class":66},"        \u002F\u002F 只对异步 chunk 生效\n",[60,685,686,688,690,692,694],{"class":62,"line":94},[60,687,595],{"class":73},[60,689,78],{"class":77},[60,691,292],{"class":127},[60,693,113],{"class":77},[60,695,696],{"class":66},"           \u002F\u002F 至少被 2 个异步 chunk 共用\n",[60,698,699,701,703,705,708,710],{"class":62,"line":119},[60,700,463],{"class":73},[60,702,78],{"class":77},[60,704,103],{"class":102},[60,706,707],{"class":106},"common-async",[60,709,110],{"class":102},[60,711,216],{"class":77},[60,713,714,716,718,720],{"class":62,"line":136},[60,715,492],{"class":73},[60,717,78],{"class":77},[60,719,307],{"class":127},[60,721,216],{"class":77},[60,723,724,726,728,730],{"class":62,"line":152},[60,725,621],{"class":73},[60,727,78],{"class":77},[60,729,321],{"class":320},[60,731,216],{"class":77},[60,733,734],{"class":62,"line":166},[60,735,340],{"class":77},[60,737,738],{"class":62,"line":176},[60,739,346],{"class":77},[348,741,742],{},[351,743,744,745,748,749,752,753,756],{},"对于动态 ",[46,746,747],{},"import()"," 的页面，如果它们都引用了同一个工具函数（如 ",[46,750,751],{},"lodash"," 的某个方法），会被提取到 ",[46,754,755],{},"common-async.js","，避免重复下载。",[33,758,760],{"id":759},"二tree-shaking","二、Tree Shaking",[23,762,763,764,196,767,770],{},"Tree Shaking 删除未使用的代码，前提是必须使用 ES Module（",[46,765,766],{},"import",[46,768,769],{},"export","）语法。",[41,772,44,774,777],{"id":773},"_1-sideeffects-false-的条件",[46,775,776],{},"sideEffects: false"," 的条件",[23,779,780,781,784,785,788],{},"在 ",[46,782,783],{},"package.json"," 中标记 ",[46,786,787],{},"\"sideEffects\": false","，告诉 Webpack 该包的模块都没有副作用（即除了导出外没有执行任何代码），可以安全地删除未被引用的导出。",[51,790,794],{"className":791,"code":792,"language":793,"meta":56,"style":56},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"name\": \"my-library\",\n  \"sideEffects\": false\n}\n","json",[46,795,796,800,824,838],{"__ignoreMap":56},[60,797,798],{"class":62,"line":63},[60,799,590],{"class":77},[60,801,802,805,809,812,814,817,820,822],{"class":62,"line":70},[60,803,804],{"class":187},"  \"",[60,806,808],{"class":807},"sseR_","name",[60,810,811],{"class":187},"\"",[60,813,78],{"class":77},[60,815,816],{"class":102}," \"",[60,818,819],{"class":106},"my-library",[60,821,811],{"class":102},[60,823,216],{"class":77},[60,825,826,828,831,833,835],{"class":62,"line":84},[60,827,804],{"class":187},[60,829,830],{"class":807},"sideEffects",[60,832,811],{"class":187},[60,834,78],{"class":77},[60,836,837],{"class":187}," false\n",[60,839,840],{"class":62,"line":94},[60,841,346],{"class":77},[23,843,844,845,848],{},"如果某些文件有副作用（如 ",[46,846,847],{},"import '.\u002Fpolyfill.js'","），则应列出：",[51,850,852],{"className":791,"code":851,"language":793,"meta":56,"style":56},"\"sideEffects\": [\".\u002Fpolyfill.js\", \".\u002Fstyle.css\"]\n",[46,853,854],{"__ignoreMap":56},[60,855,856,858,860,862,865,867,869,872,874,876,878,881,883],{"class":62,"line":63},[60,857,811],{"class":102},[60,859,830],{"class":106},[60,861,811],{"class":102},[60,863,587],{"class":864},"su5hD",[60,866,188],{"class":77},[60,868,811],{"class":102},[60,870,871],{"class":106},".\u002Fpolyfill.js",[60,873,811],{"class":102},[60,875,113],{"class":77},[60,877,816],{"class":102},[60,879,880],{"class":106},".\u002Fstyle.css",[60,882,811],{"class":102},[60,884,885],{"class":77},"]\n",[41,887,889],{"id":888},"_2-对-babel-编译的要求","2. 对 Babel 编译的要求",[23,891,892,893,896,897,900],{},"Babel 默认将 ESM 转换为 CommonJS，这会破坏 Tree Shaking。需要使用 ",[46,894,895],{},"@babel\u002Fpreset-env"," 并设置 ",[46,898,899],{},"modules: false"," 保留 ESM 结构。",[51,902,904],{"className":53,"code":903,"language":55,"meta":56,"style":56},"\u002F\u002F babel.config.js\nmodule.exports = {\n  presets: [[\"@babel\u002Fpreset-env\", { modules: false }]],\n};\n",[46,905,906,911,927,963],{"__ignoreMap":56},[60,907,908],{"class":62,"line":63},[60,909,910],{"class":66},"\u002F\u002F babel.config.js\n",[60,912,913,916,919,922,925],{"class":62,"line":70},[60,914,915],{"class":187},"module",[60,917,918],{"class":77},".",[60,920,921],{"class":187},"exports",[60,923,924],{"class":610}," =",[60,926,81],{"class":77},[60,928,929,932,934,937,939,941,943,945,947,950,952,955,958,961],{"class":62,"line":84},[60,930,931],{"class":586},"  presets",[60,933,78],{"class":77},[60,935,936],{"class":864}," [[",[60,938,811],{"class":102},[60,940,895],{"class":106},[60,942,811],{"class":102},[60,944,113],{"class":77},[60,946,160],{"class":77},[60,948,949],{"class":586}," modules",[60,951,78],{"class":77},[60,953,954],{"class":320}," false",[60,956,957],{"class":77}," }",[60,959,960],{"class":864},"]]",[60,962,216],{"class":77},[60,964,965],{"class":62,"line":94},[60,966,967],{"class":77},"};\n",[23,969,970],{},"这样 Webpack 才能分析出哪些导出被使用了。",[41,972,974],{"id":973},"_3-副作用模块如何标记如-polyfillcss-导入","3. 副作用模块如何标记（如 polyfill、CSS 导入）",[348,976,977,989],{},[351,978,979,980,983,984,545,986,988],{},"对于必须执行一次的模块（如 ",[46,981,982],{},"import '@babel\u002Fpolyfill'","），不能直接删除，因此需要在 ",[46,985,783],{},[46,987,830],{}," 中明确指定路径。",[351,990,991,992,995],{},"对于 CSS 文件（",[46,993,994],{},"import '.\u002Fstyle.css'","），通常也有副作用（样式插入 DOM），同样需要标记，否则可能会被 Tree Shaking 误删。",[51,997,999],{"className":791,"code":998,"language":793,"meta":56,"style":56},"\"sideEffects\": [\n  \"*.css\",\n  \"*.scss\",\n  \".\u002Fsrc\u002Fpolyfill.js\"\n]\n",[46,1000,1001,1014,1025,1036,1046],{"__ignoreMap":56},[60,1002,1003,1005,1007,1009,1011],{"class":62,"line":63},[60,1004,811],{"class":102},[60,1006,830],{"class":106},[60,1008,811],{"class":102},[60,1010,587],{"class":864},[60,1012,1013],{"class":77},"[\n",[60,1015,1016,1018,1021,1023],{"class":62,"line":70},[60,1017,804],{"class":102},[60,1019,1020],{"class":106},"*.css",[60,1022,811],{"class":102},[60,1024,216],{"class":77},[60,1026,1027,1029,1032,1034],{"class":62,"line":84},[60,1028,804],{"class":102},[60,1030,1031],{"class":106},"*.scss",[60,1033,811],{"class":102},[60,1035,216],{"class":77},[60,1037,1038,1040,1043],{"class":62,"line":94},[60,1039,804],{"class":102},[60,1041,1042],{"class":106},".\u002Fsrc\u002Fpolyfill.js",[60,1044,1045],{"class":102},"\"\n",[60,1047,1048],{"class":62,"line":119},[60,1049,885],{"class":77},[41,1051,1053,1054,1057],{"id":1052},"_4-usedexports-与-terser-的协作机制","4. ",[46,1055,1056],{},"usedExports"," 与 Terser 的协作机制",[348,1059,1060,1070],{},[351,1061,1062,1066,1067,31],{},[354,1063,1064],{},[46,1065,1056],{},"（Webpack 内置）：编译时标记模块中哪些导出被使用了，未被使用的导出会被标记为 ",[46,1068,1069],{},"\u002F* unused *\u002F",[351,1071,1072,1075],{},[354,1073,1074],{},"Terser","：在压缩阶段删除这些未使用的代码（包括函数、变量等）。",[51,1077,1079],{"className":53,"code":1078,"language":55,"meta":56,"style":56},"optimization: {\n  usedExports: true,   \u002F\u002F 开启标记\n  minimize: true,\n}\n",[46,1080,1081,1089,1103,1114],{"__ignoreMap":56},[60,1082,1083,1085,1087],{"class":62,"line":63},[60,1084,74],{"class":73},[60,1086,78],{"class":77},[60,1088,81],{"class":77},[60,1090,1091,1094,1096,1098,1100],{"class":62,"line":70},[60,1092,1093],{"class":73},"  usedExports",[60,1095,78],{"class":77},[60,1097,321],{"class":320},[60,1099,113],{"class":77},[60,1101,1102],{"class":66},"   \u002F\u002F 开启标记\n",[60,1104,1105,1108,1110,1112],{"class":62,"line":84},[60,1106,1107],{"class":73},"  minimize",[60,1109,78],{"class":77},[60,1111,321],{"class":320},[60,1113,216],{"class":77},[60,1115,1116],{"class":62,"line":94},[60,1117,346],{"class":77},[23,1119,1120],{},"两者协作流程：",[1122,1123,1124,1127,1130],"ol",{},[351,1125,1126],{},"Webpack 构建模块依赖图，记录每个导出的使用情况。",[351,1128,1129],{},"在生成代码时，为未使用的导出添加注释。",[351,1131,1132],{},"Terser 读取这些注释，安全地删除无用代码。",[33,1134,1136],{"id":1135},"三代码压缩","三、代码压缩",[41,1138,44,1140,1143],{"id":1139},"_1-terserwebpackplugin-详解",[46,1141,1142],{},"TerserWebpackPlugin"," 详解",[23,1145,1146],{},"Webpack 5 默认内置 Terser 插件，但也可以手动配置增强。",[51,1148,1150],{"className":53,"code":1149,"language":55,"meta":56,"style":56},"const TerserPlugin = require(\"terser-webpack-plugin\");\n\nmodule.exports = {\n  optimization: {\n    minimize: true,\n    minimizer: [\n      new TerserPlugin({\n        parallel: true, \u002F\u002F 多进程并行压缩，提升构建速度\n        extractComments: false, \u002F\u002F 是否将注释提取到单独文件（如 license）\n        terserOptions: {\n          compress: {\n            drop_console: true, \u002F\u002F 生产环境移除 console\n            drop_debugger: true,\n          },\n          output: {\n            comments: false, \u002F\u002F 移除所有注释\n            \u002F\u002F keep_fnames: false,   \u002F\u002F 保留函数名（对调试有用，但会增加体积）\n          },\n        },\n      }),\n    ],\n  },\n};\n",[46,1151,1152,1184,1190,1202,1211,1222,1232,1243,1257,1271,1280,1289,1303,1314,1319,1328,1342,1350,1354,1359,1368,1375,1380],{"__ignoreMap":56},[60,1153,1154,1158,1162,1164,1168,1171,1173,1176,1178,1181],{"class":62,"line":63},[60,1155,1157],{"class":1156},"sbsja","const",[60,1159,1161],{"class":1160},"s_hVV"," TerserPlugin",[60,1163,924],{"class":610},[60,1165,1167],{"class":1166},"sGLFI"," require",[60,1169,1170],{"class":864},"(",[60,1172,811],{"class":102},[60,1174,1175],{"class":106},"terser-webpack-plugin",[60,1177,811],{"class":102},[60,1179,1180],{"class":864},")",[60,1182,1183],{"class":77},";\n",[60,1185,1186],{"class":62,"line":70},[60,1187,1189],{"emptyLinePlaceholder":1188},true,"\n",[60,1191,1192,1194,1196,1198,1200],{"class":62,"line":84},[60,1193,915],{"class":187},[60,1195,918],{"class":77},[60,1197,921],{"class":187},[60,1199,924],{"class":610},[60,1201,81],{"class":77},[60,1203,1204,1207,1209],{"class":62,"line":94},[60,1205,1206],{"class":586},"  optimization",[60,1208,78],{"class":77},[60,1210,81],{"class":77},[60,1212,1213,1216,1218,1220],{"class":62,"line":119},[60,1214,1215],{"class":586},"    minimize",[60,1217,78],{"class":77},[60,1219,321],{"class":320},[60,1221,216],{"class":77},[60,1223,1224,1227,1229],{"class":62,"line":136},[60,1225,1226],{"class":586},"    minimizer",[60,1228,78],{"class":77},[60,1230,1231],{"class":864}," [\n",[60,1233,1234,1237,1239,1241],{"class":62,"line":152},[60,1235,1236],{"class":610},"      new",[60,1238,1161],{"class":1166},[60,1240,1170],{"class":864},[60,1242,590],{"class":77},[60,1244,1245,1248,1250,1252,1254],{"class":62,"line":166},[60,1246,1247],{"class":586},"        parallel",[60,1249,78],{"class":77},[60,1251,321],{"class":320},[60,1253,113],{"class":77},[60,1255,1256],{"class":66}," \u002F\u002F 多进程并行压缩，提升构建速度\n",[60,1258,1259,1262,1264,1266,1268],{"class":62,"line":176},[60,1260,1261],{"class":586},"        extractComments",[60,1263,78],{"class":77},[60,1265,954],{"class":320},[60,1267,113],{"class":77},[60,1269,1270],{"class":66}," \u002F\u002F 是否将注释提取到单独文件（如 license）\n",[60,1272,1273,1276,1278],{"class":62,"line":219},[60,1274,1275],{"class":586},"        terserOptions",[60,1277,78],{"class":77},[60,1279,81],{"class":77},[60,1281,1282,1285,1287],{"class":62,"line":236},[60,1283,1284],{"class":586},"          compress",[60,1286,78],{"class":77},[60,1288,81],{"class":77},[60,1290,1291,1294,1296,1298,1300],{"class":62,"line":252},[60,1292,1293],{"class":586},"            drop_console",[60,1295,78],{"class":77},[60,1297,321],{"class":320},[60,1299,113],{"class":77},[60,1301,1302],{"class":66}," \u002F\u002F 生产环境移除 console\n",[60,1304,1305,1308,1310,1312],{"class":62,"line":268},[60,1306,1307],{"class":586},"            drop_debugger",[60,1309,78],{"class":77},[60,1311,321],{"class":320},[60,1313,216],{"class":77},[60,1315,1316],{"class":62,"line":274},[60,1317,1318],{"class":77},"          },\n",[60,1320,1321,1324,1326],{"class":62,"line":284},[60,1322,1323],{"class":586},"          output",[60,1325,78],{"class":77},[60,1327,81],{"class":77},[60,1329,1330,1333,1335,1337,1339],{"class":62,"line":300},[60,1331,1332],{"class":586},"            comments",[60,1334,78],{"class":77},[60,1336,954],{"class":320},[60,1338,113],{"class":77},[60,1340,1341],{"class":66}," \u002F\u002F 移除所有注释\n",[60,1343,1344,1347],{"class":62,"line":312},[60,1345,1346],{"class":66},"            \u002F\u002F keep_fnames: false,",[60,1348,1349],{"class":66},"   \u002F\u002F 保留函数名（对调试有用，但会增加体积）\n",[60,1351,1352],{"class":62,"line":326},[60,1353,1318],{"class":77},[60,1355,1356],{"class":62,"line":331},[60,1357,1358],{"class":77},"        },\n",[60,1360,1361,1364,1366],{"class":62,"line":337},[60,1362,1363],{"class":77},"      }",[60,1365,1180],{"class":864},[60,1367,216],{"class":77},[60,1369,1370,1373],{"class":62,"line":343},[60,1371,1372],{"class":864},"    ]",[60,1374,216],{"class":77},[60,1376,1378],{"class":62,"line":1377},22,[60,1379,340],{"class":77},[60,1381,1383],{"class":62,"line":1382},23,[60,1384,967],{"class":77},[348,1386,1387,1395,1407],{},[351,1388,1389,1394],{},[354,1390,1391],{},[46,1392,1393],{},"parallel","：利用多核 CPU 加速压缩，建议开启。",[351,1396,1397,1402,1403,1406],{},[354,1398,1399],{},[46,1400,1401],{},"extractComments","：将版权注释提取到 ",[46,1404,1405],{},".LICENSE.txt","，便于符合开源协议。",[351,1408,1409,1415,1416,1419,1420,31],{},[354,1410,1411,1414],{},[46,1412,1413],{},"keep_fnames"," 权衡","：保留函数名有助于堆栈追踪调试，但会增加体积。对于生产环境一般不开启；如果依赖 ",[46,1417,1418],{},"Function.name"," 做逻辑判断，则需设为 ",[46,1421,1422],{},"true",[41,1424,1426,1427],{"id":1425},"_2-css-压缩cssminimizerwebpackplugin","2. CSS 压缩：",[46,1428,1429],{},"CssMinimizerWebpackPlugin",[23,1431,1432,1433,31],{},"替代已经废弃的 ",[46,1434,1435],{},"optimize-css-assets-webpack-plugin",[51,1437,1439],{"className":53,"code":1438,"language":55,"meta":56,"style":56},"const CssMinimizerPlugin = require(\"css-minimizer-webpack-plugin\");\n\nmodule.exports = {\n  optimization: {\n    minimizer: [\n      \"...\", \u002F\u002F 继承默认 JS 压缩（Terser）\n      new CssMinimizerPlugin({\n        parallel: true,\n        minimizerOptions: {\n          preset: [\"default\", { discardComments: { removeAll: true } }],\n        },\n      }),\n    ],\n  },\n};\n",[46,1440,1441,1465,1469,1481,1489,1497,1512,1522,1532,1541,1583,1587,1595,1601,1605],{"__ignoreMap":56},[60,1442,1443,1445,1448,1450,1452,1454,1456,1459,1461,1463],{"class":62,"line":63},[60,1444,1157],{"class":1156},[60,1446,1447],{"class":1160}," CssMinimizerPlugin",[60,1449,924],{"class":610},[60,1451,1167],{"class":1166},[60,1453,1170],{"class":864},[60,1455,811],{"class":102},[60,1457,1458],{"class":106},"css-minimizer-webpack-plugin",[60,1460,811],{"class":102},[60,1462,1180],{"class":864},[60,1464,1183],{"class":77},[60,1466,1467],{"class":62,"line":70},[60,1468,1189],{"emptyLinePlaceholder":1188},[60,1470,1471,1473,1475,1477,1479],{"class":62,"line":84},[60,1472,915],{"class":187},[60,1474,918],{"class":77},[60,1476,921],{"class":187},[60,1478,924],{"class":610},[60,1480,81],{"class":77},[60,1482,1483,1485,1487],{"class":62,"line":94},[60,1484,1206],{"class":586},[60,1486,78],{"class":77},[60,1488,81],{"class":77},[60,1490,1491,1493,1495],{"class":62,"line":119},[60,1492,1226],{"class":586},[60,1494,78],{"class":77},[60,1496,1231],{"class":864},[60,1498,1499,1502,1505,1507,1509],{"class":62,"line":136},[60,1500,1501],{"class":102},"      \"",[60,1503,1504],{"class":106},"...",[60,1506,811],{"class":102},[60,1508,113],{"class":77},[60,1510,1511],{"class":66}," \u002F\u002F 继承默认 JS 压缩（Terser）\n",[60,1513,1514,1516,1518,1520],{"class":62,"line":152},[60,1515,1236],{"class":610},[60,1517,1447],{"class":1166},[60,1519,1170],{"class":864},[60,1521,590],{"class":77},[60,1523,1524,1526,1528,1530],{"class":62,"line":166},[60,1525,1247],{"class":586},[60,1527,78],{"class":77},[60,1529,321],{"class":320},[60,1531,216],{"class":77},[60,1533,1534,1537,1539],{"class":62,"line":176},[60,1535,1536],{"class":586},"        minimizerOptions",[60,1538,78],{"class":77},[60,1540,81],{"class":77},[60,1542,1543,1546,1548,1551,1553,1555,1557,1559,1561,1564,1566,1568,1571,1573,1575,1577,1579,1581],{"class":62,"line":219},[60,1544,1545],{"class":586},"          preset",[60,1547,78],{"class":77},[60,1549,1550],{"class":864}," [",[60,1552,811],{"class":102},[60,1554,552],{"class":106},[60,1556,811],{"class":102},[60,1558,113],{"class":77},[60,1560,160],{"class":77},[60,1562,1563],{"class":586}," discardComments",[60,1565,78],{"class":77},[60,1567,160],{"class":77},[60,1569,1570],{"class":586}," removeAll",[60,1572,78],{"class":77},[60,1574,321],{"class":320},[60,1576,957],{"class":77},[60,1578,957],{"class":77},[60,1580,199],{"class":864},[60,1582,216],{"class":77},[60,1584,1585],{"class":62,"line":236},[60,1586,1358],{"class":77},[60,1588,1589,1591,1593],{"class":62,"line":252},[60,1590,1363],{"class":77},[60,1592,1180],{"class":864},[60,1594,216],{"class":77},[60,1596,1597,1599],{"class":62,"line":268},[60,1598,1372],{"class":864},[60,1600,216],{"class":77},[60,1602,1603],{"class":62,"line":274},[60,1604,340],{"class":77},[60,1606,1607],{"class":62,"line":284},[60,1608,967],{"class":77},[23,1610,1611,1612,1615],{},"注意：CSS 压缩器应放在 ",[46,1613,1614],{},"minimizer"," 数组中，与 JS 压缩器并列。",[33,1617,1619],{"id":1618},"四资源模块优化","四、资源模块优化",[23,1621,1622,1623,391,1626,391,1629,31],{},"Webpack 5 内置了资源模块（asset modules），取代 ",[46,1624,1625],{},"file-loader",[46,1627,1628],{},"url-loader",[46,1630,1631],{},"raw-loader",[41,1633,1635],{"id":1634},"_1-asset-模块类型","1. asset 模块类型",[1637,1638,1639,1652],"table",{},[1640,1641,1642],"thead",{},[1643,1644,1645,1649],"tr",{},[1646,1647,1648],"th",{},"类型",[1646,1650,1651],{},"作用",[1653,1654,1655,1669,1686,1698],"tbody",{},[1643,1656,1657,1663],{},[1658,1659,1660],"td",{},[46,1661,1662],{},"asset\u002Fresource",[1658,1664,1665,1666,1668],{},"单独输出文件，通过 URL 引用（相当于 ",[46,1667,1625],{},"）",[1643,1670,1671,1676],{},[1658,1672,1673],{},[46,1674,1675],{},"asset\u002Finline",[1658,1677,1678,1679,1681,1682,1685],{},"导出资源的 DataURI（相当于 ",[46,1680,1628],{}," 且 ",[46,1683,1684],{},"limit"," 无限）",[1643,1687,1688,1693],{},[1658,1689,1690],{},[46,1691,1692],{},"asset\u002Fsource",[1658,1694,1695,1696,1668],{},"导出资源的源代码（相当于 ",[46,1697,1631],{},[1643,1699,1700,1705],{},[1658,1701,1702],{},[46,1703,1704],{},"asset",[1658,1706,1707],{},"自动决定：小于某个阈值时内联为 DataURI，否则输出文件",[41,1709,1711],{"id":1710},"_2-小资源内嵌的阈值设置","2. 小资源内嵌的阈值设置",[51,1713,1715],{"className":53,"code":1714,"language":55,"meta":56,"style":56},"module: {\n  rules: [\n    {\n      test: \u002F\\.(png|jpg|svg)$\u002F,\n      type: 'asset',\n      parser: {\n        dataUrlCondition: {\n          maxSize: 8 * 1024, \u002F\u002F 8KB 以下的图片转为 Base64\n        },\n      },\n    },\n  ],\n}\n",[46,1716,1717,1725,1734,1739,1777,1792,1801,1810,1831,1835,1839,1843,1850],{"__ignoreMap":56},[60,1718,1719,1721,1723],{"class":62,"line":63},[60,1720,915],{"class":73},[60,1722,78],{"class":77},[60,1724,81],{"class":77},[60,1726,1727,1730,1732],{"class":62,"line":70},[60,1728,1729],{"class":73},"  rules",[60,1731,78],{"class":77},[60,1733,1231],{"class":586},[60,1735,1736],{"class":62,"line":84},[60,1737,1738],{"class":77},"    {\n",[60,1740,1741,1744,1746,1748,1751,1754,1757,1760,1763,1765,1768,1770,1773,1775],{"class":62,"line":94},[60,1742,1743],{"class":586},"      test",[60,1745,78],{"class":77},[60,1747,184],{"class":102},[60,1749,1750],{"class":191},"\\.",[60,1752,1170],{"class":1753},"s-KJb",[60,1755,1756],{"class":202},"png",[60,1758,1759],{"class":610},"|",[60,1761,1762],{"class":202},"jpg",[60,1764,1759],{"class":610},[60,1766,1767],{"class":202},"svg",[60,1769,1180],{"class":1753},[60,1771,1772],{"class":582},"$",[60,1774,196],{"class":102},[60,1776,216],{"class":77},[60,1778,1779,1782,1784,1786,1788,1790],{"class":62,"line":119},[60,1780,1781],{"class":586},"      type",[60,1783,78],{"class":77},[60,1785,103],{"class":102},[60,1787,1704],{"class":106},[60,1789,110],{"class":102},[60,1791,216],{"class":77},[60,1793,1794,1797,1799],{"class":62,"line":136},[60,1795,1796],{"class":586},"      parser",[60,1798,78],{"class":77},[60,1800,81],{"class":77},[60,1802,1803,1806,1808],{"class":62,"line":152},[60,1804,1805],{"class":586},"        dataUrlCondition",[60,1807,78],{"class":77},[60,1809,81],{"class":77},[60,1811,1812,1815,1817,1820,1823,1826,1828],{"class":62,"line":166},[60,1813,1814],{"class":586},"          maxSize",[60,1816,78],{"class":77},[60,1818,1819],{"class":127}," 8",[60,1821,1822],{"class":610}," *",[60,1824,1825],{"class":127}," 1024",[60,1827,113],{"class":77},[60,1829,1830],{"class":66}," \u002F\u002F 8KB 以下的图片转为 Base64\n",[60,1832,1833],{"class":62,"line":176},[60,1834,1358],{"class":77},[60,1836,1837],{"class":62,"line":219},[60,1838,271],{"class":77},[60,1840,1841],{"class":62,"line":236},[60,1842,334],{"class":77},[60,1844,1845,1848],{"class":62,"line":252},[60,1846,1847],{"class":586},"  ]",[60,1849,216],{"class":77},[60,1851,1852],{"class":62,"line":268},[60,1853,346],{"class":77},[348,1855,1856],{},[351,1857,1858],{},"内联可以减少 HTTP 请求，但会增加 HTML 或 CSS 的体积，需要权衡。",[41,1860,1862,1863,1866],{"id":1861},"_3-指纹命名contenthash的最佳实践","3. 指纹命名（",[46,1864,1865],{},"[contenthash]","）的最佳实践",[23,1868,1869,1870,1872],{},"输出文件名使用 ",[46,1871,1865],{}," 实现长期缓存：",[51,1874,1876],{"className":53,"code":1875,"language":55,"meta":56,"style":56},"output: {\n  filename: '[name].[contenthash].js',\n  chunkFilename: '[name].[contenthash].chunk.js',\n},\n",[46,1877,1878,1887,1903,1919],{"__ignoreMap":56},[60,1879,1880,1883,1885],{"class":62,"line":63},[60,1881,1882],{"class":73},"output",[60,1884,78],{"class":77},[60,1886,81],{"class":77},[60,1888,1889,1892,1894,1896,1899,1901],{"class":62,"line":70},[60,1890,1891],{"class":73},"  filename",[60,1893,78],{"class":77},[60,1895,103],{"class":102},[60,1897,1898],{"class":106},"[name].[contenthash].js",[60,1900,110],{"class":102},[60,1902,216],{"class":77},[60,1904,1905,1908,1910,1912,1915,1917],{"class":62,"line":84},[60,1906,1907],{"class":73},"  chunkFilename",[60,1909,78],{"class":77},[60,1911,103],{"class":102},[60,1913,1914],{"class":106},"[name].[contenthash].chunk.js",[60,1916,110],{"class":102},[60,1918,216],{"class":77},[60,1920,1921],{"class":62,"line":94},[60,1922,1923],{"class":77},"},\n",[348,1925,1926,1931],{},[351,1927,1928,1930],{},[46,1929,1865],{}," 基于模块内容生成，内容不变则哈希不变，利于浏览器缓存。",[351,1932,1933,1934,31],{},"对于 CSS 也使用 ",[46,1935,1865],{},[41,1937,1939,1940,1943,1944],{"id":1938},"_4-预获取预加载-webpackprefetch-true-与-webpackpreload-true","4. 预获取\u002F预加载：",[46,1941,1942],{},"\u002F* webpackPrefetch: true *\u002F"," 与 ",[46,1945,1946],{},"\u002F* webpackPreload: true *\u002F",[348,1948,1949],{},[351,1950,1951,1954],{},[354,1952,1953],{},"预获取（Prefetch）","：浏览器空闲时提前下载异步 chunk，用于非关键资源（如下一个页面的 JS）。",[51,1956,1958],{"className":53,"code":1957,"language":55,"meta":56,"style":56},"import(\u002F* webpackPrefetch: true *\u002F \".\u002FLoginModal.vue\");\n",[46,1959,1960],{"__ignoreMap":56},[60,1961,1962,1964,1966,1968,1970,1973,1975,1977],{"class":62,"line":63},[60,1963,766],{"class":1166},[60,1965,1170],{"class":864},[60,1967,1942],{"class":66},[60,1969,816],{"class":102},[60,1971,1972],{"class":106},".\u002FLoginModal.vue",[60,1974,811],{"class":102},[60,1976,1180],{"class":864},[60,1978,1183],{"class":77},[348,1980,1981],{},[351,1982,1983,1986],{},[354,1984,1985],{},"预加载（Preload）","：与当前页面同优先级，立即下载，用于当前页面必需但未立即执行的资源。",[51,1988,1990],{"className":53,"code":1989,"language":55,"meta":56,"style":56},"import(\u002F* webpackPreload: true *\u002F \".\u002FCriticalChart.vue\");\n",[46,1991,1992],{"__ignoreMap":56},[60,1993,1994,1996,1998,2000,2002,2005,2007,2009],{"class":62,"line":63},[60,1995,766],{"class":1166},[60,1997,1170],{"class":864},[60,1999,1946],{"class":66},[60,2001,816],{"class":102},[60,2003,2004],{"class":106},".\u002FCriticalChart.vue",[60,2006,811],{"class":102},[60,2008,1180],{"class":864},[60,2010,1183],{"class":77},[23,2012,2013,2016,2017,2020,2021,2024],{},[354,2014,2015],{},"原理","：Webpack 会在生成的 HTML 中插入 ",[46,2018,2019],{},"\u003Clink rel=\"prefetch\u002Fpreload\" href=\"...\">"," 标签，告诉浏览器提前加载。需要 ",[46,2022,2023],{},"HtmlWebpackPlugin"," 配合。",[23,2026,2027,2030],{},[354,2028,2029],{},"时机","：prefetch 适合懒加载页面的资源；preload 适合当前路由下立即需要但未解析的组件。",[23,2032,2033],{},"注意：过度使用 preload 会增加首屏加载负担。",[2035,2036,2037],"h2",{"id":2037},"总结",[1637,2039,2040,2050],{},[1640,2041,2042],{},[1643,2043,2044,2047],{},[1646,2045,2046],{},"优化类别",[1646,2048,2049],{},"关键技术",[1653,2051,2052,2071,2086,2101],{},[1643,2053,2054,2059],{},[1658,2055,2056],{},[354,2057,2058],{},"代码分割",[1658,2060,2061,2063,2064,391,2066,391,2068,2070],{},[46,2062,48],{}," 配置 ",[46,2065,358],{},[46,2067,386],{},[46,2069,642],{}," 等",[1643,2072,2073,2078],{},[1658,2074,2075],{},[354,2076,2077],{},"Tree Shaking",[1658,2079,2080,2082,2083,2085],{},[46,2081,776],{},"、Babel 保留 ESM、",[46,2084,1056],{}," + Terser",[1643,2087,2088,2093],{},[1658,2089,2090],{},[354,2091,2092],{},"代码压缩",[1658,2094,2095,2097,2098,2100],{},[46,2096,1142],{},"（JS）、",[46,2099,1429],{},"（CSS）",[1643,2102,2103,2108],{},[1658,2104,2105],{},[354,2106,2107],{},"资源优化",[1658,2109,2110,2111,2113],{},"asset 模块、小资源内嵌阈值、",[46,2112,1865],{}," 指纹、prefetch\u002Fpreload",[23,2115,2116],{},"合理运用这些配置，能显著减少产物体积、优化缓存策略、提升页面加载性能。",[2035,2118,2119],{"id":2119},"参考文献",[23,2121,2122],{},"以下链接在编写时均可正常访问：",[1637,2124,2125,2135],{},[1640,2126,2127],{},[1643,2128,2129,2132],{},[1646,2130,2131],{},"资料",[1646,2133,2134],{},"说明",[1653,2136,2137,2149,2159],{},[1643,2138,2139,2146],{},[1658,2140,2141],{},[27,2142,2058],{"href":2143,"rel":2144},"https:\u002F\u002Fwebpack.js.org\u002Fguides\u002Fcode-splitting\u002F",[2145],"nofollow",[1658,2147,2148],{},"官方",[1643,2150,2151,2157],{},[1658,2152,2153],{},[27,2154,2077],{"href":2155,"rel":2156},"https:\u002F\u002Fwebpack.js.org\u002Fguides\u002Ftree-shaking\u002F",[2145],[1658,2158,2148],{},[1643,2160,2161,2168],{},[1658,2162,2163],{},[27,2164,2167],{"href":2165,"rel":2166},"https:\u002F\u002Fwebpack.js.org\u002Fconfiguration\u002Foptimization\u002F",[2145],"Optimization",[1658,2169,2170],{},"配置项",[2172,2173,2174],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjYin, html code.shiki .sjYin{--shiki-light:#90A4AE;--shiki-light-font-weight:inherit;--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sQRbd, html code.shiki .sQRbd{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s-KJb, html code.shiki .s-KJb{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":56,"searchDepth":70,"depth":70,"links":2176},[2177,2178,2179,2180,2181,2182],{"id":35,"depth":84,"text":36},{"id":759,"depth":84,"text":760},{"id":1135,"depth":84,"text":1136},{"id":1618,"depth":84,"text":1619},{"id":2037,"depth":70,"text":2037},{"id":2119,"depth":70,"text":2119},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fchunks","knowledge\u002Fknowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fchunks.md","md",{"items":2188},[2189,2191,2195,2199,2203,2207],{"path":29,"title":30,"description":2190,"category":10,"score":136},"Webpack 是静态模块打包器：从入口递归解析依赖，经 Loader 转换后输出一个或多个 bundle。与 Vite 对比见 Webpack 与 Vite。",{"path":2192,"title":2193,"description":2194,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fcompany","企业级实践","大型前端项目在 Webpack 场景下的多环境拆分、Docker 构建缓存、自定义 CLI 与微前端（Module Federation \u002F single-spa）等实践。入门见 工程化概览。",{"path":2196,"title":2197,"description":2198,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader","Loader","Loader 在 Webpack 构建链中把源文件转为可打包的 JS 模块（如 TS、SCSS、Vue SFC）。见 工作原理。",{"path":2200,"title":2201,"description":2202,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fadvanced","进阶配置","Webpack 进阶场景：多页面（MPA）、devServer、环境变量注入、Source Map、Module Federation 等。基础见 工作原理。",{"path":2204,"title":2205,"description":2206,"category":10,"score":136},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin","Plugin","Webpack 插件在构建生命周期钩子上扩展能力（修改资源、生成 HTML、上传 CDN 等）。背景见 工作原理；与 Loader 分工：Loader 转换单文件，插件面向整体构建。",{"path":2208,"title":2209,"description":2210,"category":10,"score":94},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fproject\u002Fother","其他配置","除 ESLint、Prettier 等规范文件外，仓库中常见的工具链与包管理配置如下。见 工程化概览。",{"series":2212,"title":12,"items":2213,"index":63,"prev":2225,"next":2226},"booklet\u002Fproject\u002Fwebpack",[2214,2216,2217,2219,2221,2223],{"path":2200,"title":2201,"date":2215,"pinned":15},"2021-10-18",{"path":7,"title":8,"date":14,"pinned":15},{"path":2192,"title":2193,"date":2218,"pinned":15},"2024-07-30",{"path":2196,"title":2197,"date":2220,"pinned":15},"2022-11-14",{"path":2204,"title":2205,"date":2222,"pinned":15},"2020-08-27",{"path":29,"title":30,"date":2224,"pinned":15},"2025-12-19",{"path":2200,"title":2201,"date":2215,"pinned":15},{"path":2192,"title":2193,"date":2218,"pinned":15}]