[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin":3086,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin":3108},{"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":3082,"stem":3083,"id":3084,"extension":3085},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin","Plugin","Webpack 插件在构建生命周期钩子上扩展能力（修改资源、生成 HTML、上传 CDN 等）。背景见 工作原理；与 Loader 分工：Loader 转换单文件，插件面向整体构建。","技能小册",[12,13],"webpack","plugin","2020-08-27",false,{"type":17,"value":18,"toc":3072},"minimark",[19,22,42,47,63,501,507,550,554,562,565,656,662,665,768,773,1013,1017,1021,1274,1278,1520,1524,1720,1724,2071,2078,2084,2138,2144,2431,2436,2588,2592,2595,2599,2623,2638,2642,2649,2875,2878,2882,2910,2914,3012,3024,3027,3030,3068],[20,21,8],"h1",{"id":13},[23,24,25,26,30,31,36,37,41],"p",{},"Webpack ",[27,28,29],"strong",{},"插件","在构建生命周期钩子上扩展能力（修改资源、生成 HTML、上传 CDN 等）。背景见 ",[32,33,35],"a",{"href":34},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow","工作原理","；与 ",[32,38,40],{"href":39},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader","Loader"," 分工：Loader 转换单文件，插件面向整体构建。",[43,44,46],"h3",{"id":45},"一插件基本架构","一、插件基本架构",[23,48,49,50,54,55,58,59,62],{},"每个插件都是一个具有 ",[51,52,53],"code",{},"apply(compiler)"," 方法的类或对象。在 ",[51,56,57],{},"apply"," 中通过 ",[51,60,61],{},"compiler.hooks"," 注册钩子回调。",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","class MyPlugin {\n  apply(compiler) {\n    \u002F\u002F 同步钩子使用 tap\n    compiler.hooks.compile.tap(\"MyPlugin\", (params) => {\n      console.log(\"开始编译\");\n    });\n\n    \u002F\u002F 异步串行钩子使用 tapAsync（调用 callback）\n    compiler.hooks.emit.tapAsync(\"MyPlugin\", (compilation, callback) => {\n      setTimeout(() => {\n        console.log(\"发射文件前\");\n        callback();\n      }, 1000);\n    });\n\n    \u002F\u002F 异步并行钩子使用 tapPromise（返回 Promise）\n    compiler.hooks.run.tapPromise(\"MyPlugin\", (compiler) => {\n      return new Promise((resolve) => {\n        setTimeout(() => {\n          console.log(\"运行开始\");\n          resolve();\n        }, 500);\n      });\n    });\n  }\n}\n","js","",[51,71,72,89,108,115,168,193,203,210,216,261,276,299,309,323,332,337,343,382,410,424,447,457,470,480,489,495],{"__ignoreMap":69},[73,74,77,81,85],"span",{"class":75,"line":76},"line",1,[73,78,80],{"class":79},"sbsja","class",[73,82,84],{"class":83},"sbgvK"," MyPlugin",[73,86,88],{"class":87},"sP7_E"," {\n",[73,90,92,96,99,103,106],{"class":75,"line":91},2,[73,93,95],{"class":94},"sVXei","  apply",[73,97,98],{"class":87},"(",[73,100,102],{"class":101},"s99_P","compiler",[73,104,105],{"class":87},")",[73,107,88],{"class":87},[73,109,111],{"class":75,"line":110},3,[73,112,114],{"class":113},"sutJx","    \u002F\u002F 同步钩子使用 tap\n",[73,116,118,122,125,128,130,133,135,139,142,146,150,152,155,158,161,163,166],{"class":75,"line":117},4,[73,119,121],{"class":120},"su5hD","    compiler",[73,123,124],{"class":87},".",[73,126,127],{"class":120},"hooks",[73,129,124],{"class":87},[73,131,132],{"class":120},"compile",[73,134,124],{"class":87},[73,136,138],{"class":137},"sGLFI","tap",[73,140,98],{"class":141},"skxfh",[73,143,145],{"class":144},"sjJ54","\"",[73,147,149],{"class":148},"s_sjI","MyPlugin",[73,151,145],{"class":144},[73,153,154],{"class":87},",",[73,156,157],{"class":87}," (",[73,159,160],{"class":101},"params",[73,162,105],{"class":87},[73,164,165],{"class":79}," =>",[73,167,88],{"class":87},[73,169,171,174,176,179,181,183,186,188,190],{"class":75,"line":170},5,[73,172,173],{"class":120},"      console",[73,175,124],{"class":87},[73,177,178],{"class":137},"log",[73,180,98],{"class":141},[73,182,145],{"class":144},[73,184,185],{"class":148},"开始编译",[73,187,145],{"class":144},[73,189,105],{"class":141},[73,191,192],{"class":87},";\n",[73,194,196,199,201],{"class":75,"line":195},6,[73,197,198],{"class":87},"    }",[73,200,105],{"class":141},[73,202,192],{"class":87},[73,204,206],{"class":75,"line":205},7,[73,207,209],{"emptyLinePlaceholder":208},true,"\n",[73,211,213],{"class":75,"line":212},8,[73,214,215],{"class":113},"    \u002F\u002F 异步串行钩子使用 tapAsync（调用 callback）\n",[73,217,219,221,223,225,227,230,232,235,237,239,241,243,245,247,250,252,255,257,259],{"class":75,"line":218},9,[73,220,121],{"class":120},[73,222,124],{"class":87},[73,224,127],{"class":120},[73,226,124],{"class":87},[73,228,229],{"class":120},"emit",[73,231,124],{"class":87},[73,233,234],{"class":137},"tapAsync",[73,236,98],{"class":141},[73,238,145],{"class":144},[73,240,149],{"class":148},[73,242,145],{"class":144},[73,244,154],{"class":87},[73,246,157],{"class":87},[73,248,249],{"class":101},"compilation",[73,251,154],{"class":87},[73,253,254],{"class":101}," callback",[73,256,105],{"class":87},[73,258,165],{"class":79},[73,260,88],{"class":87},[73,262,264,267,269,272,274],{"class":75,"line":263},10,[73,265,266],{"class":137},"      setTimeout",[73,268,98],{"class":141},[73,270,271],{"class":87},"()",[73,273,165],{"class":79},[73,275,88],{"class":87},[73,277,279,282,284,286,288,290,293,295,297],{"class":75,"line":278},11,[73,280,281],{"class":120},"        console",[73,283,124],{"class":87},[73,285,178],{"class":137},[73,287,98],{"class":141},[73,289,145],{"class":144},[73,291,292],{"class":148},"发射文件前",[73,294,145],{"class":144},[73,296,105],{"class":141},[73,298,192],{"class":87},[73,300,302,305,307],{"class":75,"line":301},12,[73,303,304],{"class":137},"        callback",[73,306,271],{"class":141},[73,308,192],{"class":87},[73,310,312,315,319,321],{"class":75,"line":311},13,[73,313,314],{"class":87},"      },",[73,316,318],{"class":317},"srdBf"," 1000",[73,320,105],{"class":141},[73,322,192],{"class":87},[73,324,326,328,330],{"class":75,"line":325},14,[73,327,198],{"class":87},[73,329,105],{"class":141},[73,331,192],{"class":87},[73,333,335],{"class":75,"line":334},15,[73,336,209],{"emptyLinePlaceholder":208},[73,338,340],{"class":75,"line":339},16,[73,341,342],{"class":113},"    \u002F\u002F 异步并行钩子使用 tapPromise（返回 Promise）\n",[73,344,346,348,350,352,354,357,359,362,364,366,368,370,372,374,376,378,380],{"class":75,"line":345},17,[73,347,121],{"class":120},[73,349,124],{"class":87},[73,351,127],{"class":120},[73,353,124],{"class":87},[73,355,356],{"class":120},"run",[73,358,124],{"class":87},[73,360,361],{"class":137},"tapPromise",[73,363,98],{"class":141},[73,365,145],{"class":144},[73,367,149],{"class":148},[73,369,145],{"class":144},[73,371,154],{"class":87},[73,373,157],{"class":87},[73,375,102],{"class":101},[73,377,105],{"class":87},[73,379,165],{"class":79},[73,381,88],{"class":87},[73,383,385,389,393,397,399,401,404,406,408],{"class":75,"line":384},18,[73,386,388],{"class":387},"sVHd0","      return",[73,390,392],{"class":391},"smGrS"," new",[73,394,396],{"class":395},"sZMiF"," Promise",[73,398,98],{"class":141},[73,400,98],{"class":87},[73,402,403],{"class":101},"resolve",[73,405,105],{"class":87},[73,407,165],{"class":79},[73,409,88],{"class":87},[73,411,413,416,418,420,422],{"class":75,"line":412},19,[73,414,415],{"class":137},"        setTimeout",[73,417,98],{"class":141},[73,419,271],{"class":87},[73,421,165],{"class":79},[73,423,88],{"class":87},[73,425,427,430,432,434,436,438,441,443,445],{"class":75,"line":426},20,[73,428,429],{"class":120},"          console",[73,431,124],{"class":87},[73,433,178],{"class":137},[73,435,98],{"class":141},[73,437,145],{"class":144},[73,439,440],{"class":148},"运行开始",[73,442,145],{"class":144},[73,444,105],{"class":141},[73,446,192],{"class":87},[73,448,450,453,455],{"class":75,"line":449},21,[73,451,452],{"class":137},"          resolve",[73,454,271],{"class":141},[73,456,192],{"class":87},[73,458,460,463,466,468],{"class":75,"line":459},22,[73,461,462],{"class":87},"        },",[73,464,465],{"class":317}," 500",[73,467,105],{"class":141},[73,469,192],{"class":87},[73,471,473,476,478],{"class":75,"line":472},23,[73,474,475],{"class":87},"      }",[73,477,105],{"class":141},[73,479,192],{"class":87},[73,481,483,485,487],{"class":75,"line":482},24,[73,484,198],{"class":87},[73,486,105],{"class":141},[73,488,192],{"class":87},[73,490,492],{"class":75,"line":491},25,[73,493,494],{"class":87},"  }\n",[73,496,498],{"class":75,"line":497},26,[73,499,500],{"class":87},"}\n",[23,502,503,506],{},[27,504,505],{},"钩子类型决定注册方式","：",[508,509,510,519,531,544],"ul",{},[511,512,513,516,517],"li",{},[51,514,515],{},"SyncHook","：只能用 ",[51,518,138],{},[511,520,521,516,524,526,527,530],{},[51,522,523],{},"SyncBailHook",[51,525,138],{},"，返回非 ",[51,528,529],{},"undefined"," 则中断",[511,532,533,536,537,539,540,539,542],{},[51,534,535],{},"AsyncParallelHook","：可用 ",[51,538,138],{},"\u002F",[51,541,234],{},[51,543,361],{},[511,545,546,549],{},[51,547,548],{},"AsyncSeriesHook","：同上，但串行执行",[43,551,553],{"id":552},"二compiler-与-compilation-核心属性","二、Compiler 与 Compilation 核心属性",[555,556,558,559,561],"h4",{"id":557},"_1-compiler-对象","1. ",[51,560,102],{}," 对象",[23,563,564],{},"代表整个 Webpack 实例，包含了配置、文件系统、插件集合等。",[566,567,568,584],"table",{},[569,570,571],"thead",{},[572,573,574,578,581],"tr",{},[575,576,577],"th",{},"属性",[575,579,580],{},"说明",[575,582,583],{},"常用场景",[585,586,587,601,618,631,643],"tbody",{},[572,588,589,595,598],{},[590,591,592],"td",{},[51,593,594],{},"compiler.options",[590,596,597],{},"最终的合并配置",[590,599,600],{},"读取用户配置项",[572,602,603,608,615],{},[590,604,605],{},[51,606,607],{},"compiler.inputFileSystem",[590,609,610,611,614],{},"读取文件的文件系统（默认 ",[51,612,613],{},"fs","）",[590,616,617],{},"手动读取文件",[572,619,620,625,628],{},[590,621,622],{},[51,623,624],{},"compiler.outputFileSystem",[590,626,627],{},"输出文件的文件系统",[590,629,630],{},"写入自定义文件",[572,632,633,637,640],{},[590,634,635],{},[51,636,61],{},[590,638,639],{},"所有生命周期钩子",[590,641,642],{},"注册插件逻辑",[572,644,645,650,653],{},[590,646,647],{},[51,648,649],{},"compiler.context",[590,651,652],{},"项目根目录绝对路径",[590,654,655],{},"解析相对路径",[555,657,659,660,561],{"id":658},"_2-compilation-对象","2. ",[51,661,249],{},[23,663,664],{},"代表一次完整的资源构建过程，包含当前打包的所有模块、chunk、生成资源等。",[566,666,667,677],{},[569,668,669],{},[572,670,671,673,675],{},[575,672,577],{},[575,674,580],{},[575,676,583],{},[585,678,679,692,705,720,737,752],{},[572,680,681,686,689],{},[590,682,683],{},[51,684,685],{},"compilation.modules",[590,687,688],{},"所有模块的集合（Set）",[590,690,691],{},"遍历所有模块，筛选特定模块",[572,693,694,699,702],{},[590,695,696],{},[51,697,698],{},"compilation.chunks",[590,700,701],{},"所有 chunk 的集合",[590,703,704],{},"修改 chunk 名称或内容",[572,706,707,712,715],{},[590,708,709],{},[51,710,711],{},"compilation.assets",[590,713,714],{},"生成的文件资源对象（key: 文件名, value: Source）",[590,716,717],{},[27,718,719],{},"修改、添加、删除输出资源",[572,721,722,731,734],{},[590,723,724,727,728],{},[51,725,726],{},"compilation.errors"," \u002F ",[51,729,730],{},"warnings",[590,732,733],{},"错误\u002F警告数组",[590,735,736],{},"收集并上报错误",[572,738,739,744,749],{},[590,740,741],{},[51,742,743],{},"compilation.inputFileSystem",[590,745,746,747],{},"同 ",[51,748,607],{},[590,750,751],{},"读取文件",[572,753,754,759,765],{},[590,755,756],{},[51,757,758],{},"compilation.getStats()",[590,760,761,762,561],{},"生成 ",[51,763,764],{},"stats",[590,766,767],{},"输出构建统计信息",[23,769,770,506],{},[27,771,772],{},"修改 assets 示例",[64,774,776],{"className":66,"code":775,"language":68,"meta":69,"style":69},"compiler.hooks.emit.tapAsync(\"MyPlugin\", (compilation, callback) => {\n  \u002F\u002F 添加一个新文件\n  compilation.assets[\"my-version.json\"] = {\n    source: () => JSON.stringify({ version: \"1.0.0\" }),\n    size: () => 20,\n  };\n  \u002F\u002F 或使用 webpack-sources\n  const { RawSource } = require(\"webpack-sources\");\n  compilation.assets[\"info.txt\"] = new RawSource(\"Build completed\");\n  callback();\n});\n",[51,777,778,818,823,851,899,915,920,925,957,995,1004],{"__ignoreMap":69},[73,779,780,782,784,786,788,790,792,794,796,798,800,802,804,806,808,810,812,814,816],{"class":75,"line":76},[73,781,102],{"class":120},[73,783,124],{"class":87},[73,785,127],{"class":120},[73,787,124],{"class":87},[73,789,229],{"class":120},[73,791,124],{"class":87},[73,793,234],{"class":137},[73,795,98],{"class":120},[73,797,145],{"class":144},[73,799,149],{"class":148},[73,801,145],{"class":144},[73,803,154],{"class":87},[73,805,157],{"class":87},[73,807,249],{"class":101},[73,809,154],{"class":87},[73,811,254],{"class":101},[73,813,105],{"class":87},[73,815,165],{"class":79},[73,817,88],{"class":87},[73,819,820],{"class":75,"line":91},[73,821,822],{"class":113},"  \u002F\u002F 添加一个新文件\n",[73,824,825,828,830,833,836,838,841,843,846,849],{"class":75,"line":110},[73,826,827],{"class":120},"  compilation",[73,829,124],{"class":87},[73,831,832],{"class":120},"assets",[73,834,835],{"class":141},"[",[73,837,145],{"class":144},[73,839,840],{"class":148},"my-version.json",[73,842,145],{"class":144},[73,844,845],{"class":141},"] ",[73,847,848],{"class":391},"=",[73,850,88],{"class":87},[73,852,853,856,859,862,864,868,870,873,875,878,881,883,886,889,891,894,896],{"class":75,"line":117},[73,854,855],{"class":137},"    source",[73,857,858],{"class":87},":",[73,860,861],{"class":87}," ()",[73,863,165],{"class":79},[73,865,867],{"class":866},"s_hVV"," JSON",[73,869,124],{"class":87},[73,871,872],{"class":137},"stringify",[73,874,98],{"class":141},[73,876,877],{"class":87},"{",[73,879,880],{"class":141}," version",[73,882,858],{"class":87},[73,884,885],{"class":144}," \"",[73,887,888],{"class":148},"1.0.0",[73,890,145],{"class":144},[73,892,893],{"class":87}," }",[73,895,105],{"class":141},[73,897,898],{"class":87},",\n",[73,900,901,904,906,908,910,913],{"class":75,"line":170},[73,902,903],{"class":137},"    size",[73,905,858],{"class":87},[73,907,861],{"class":87},[73,909,165],{"class":79},[73,911,912],{"class":317}," 20",[73,914,898],{"class":87},[73,916,917],{"class":75,"line":195},[73,918,919],{"class":87},"  };\n",[73,921,922],{"class":75,"line":205},[73,923,924],{"class":113},"  \u002F\u002F 或使用 webpack-sources\n",[73,926,927,930,933,936,938,941,944,946,948,951,953,955],{"class":75,"line":212},[73,928,929],{"class":79},"  const",[73,931,932],{"class":87}," {",[73,934,935],{"class":866}," RawSource",[73,937,893],{"class":87},[73,939,940],{"class":391}," =",[73,942,943],{"class":137}," require",[73,945,98],{"class":141},[73,947,145],{"class":144},[73,949,950],{"class":148},"webpack-sources",[73,952,145],{"class":144},[73,954,105],{"class":141},[73,956,192],{"class":87},[73,958,959,961,963,965,967,969,972,974,976,978,980,982,984,986,989,991,993],{"class":75,"line":218},[73,960,827],{"class":120},[73,962,124],{"class":87},[73,964,832],{"class":120},[73,966,835],{"class":141},[73,968,145],{"class":144},[73,970,971],{"class":148},"info.txt",[73,973,145],{"class":144},[73,975,845],{"class":141},[73,977,848],{"class":391},[73,979,392],{"class":391},[73,981,935],{"class":137},[73,983,98],{"class":141},[73,985,145],{"class":144},[73,987,988],{"class":148},"Build completed",[73,990,145],{"class":144},[73,992,105],{"class":141},[73,994,192],{"class":87},[73,996,997,1000,1002],{"class":75,"line":263},[73,998,999],{"class":137},"  callback",[73,1001,271],{"class":141},[73,1003,192],{"class":87},[73,1005,1006,1009,1011],{"class":75,"line":278},[73,1007,1008],{"class":87},"}",[73,1010,105],{"class":120},[73,1012,192],{"class":87},[43,1014,1016],{"id":1015},"三常见自定义插件实现","三、常见自定义插件实现",[555,1018,1020],{"id":1019},"_1-生成额外文件如-manifestjson版本信息","1. 生成额外文件（如 manifest.json、版本信息）",[64,1022,1024],{"className":66,"code":1023,"language":68,"meta":69,"style":69},"class GenerateManifestPlugin {\n  apply(compiler) {\n    compiler.hooks.emit.tapAsync(\"GenerateManifestPlugin\", (compilation, callback) => {\n      const manifest = {\n        timestamp: Date.now(),\n        files: Object.keys(compilation.assets),\n      };\n      const json = JSON.stringify(manifest, null, 2);\n      compilation.assets[\"manifest.json\"] = {\n        source: () => json,\n        size: () => json.length,\n      };\n      callback();\n    });\n  }\n}\n",[51,1025,1026,1035,1047,1088,1100,1119,1146,1151,1186,1210,1225,1245,1249,1258,1266,1270],{"__ignoreMap":69},[73,1027,1028,1030,1033],{"class":75,"line":76},[73,1029,80],{"class":79},[73,1031,1032],{"class":83}," GenerateManifestPlugin",[73,1034,88],{"class":87},[73,1036,1037,1039,1041,1043,1045],{"class":75,"line":91},[73,1038,95],{"class":94},[73,1040,98],{"class":87},[73,1042,102],{"class":101},[73,1044,105],{"class":87},[73,1046,88],{"class":87},[73,1048,1049,1051,1053,1055,1057,1059,1061,1063,1065,1067,1070,1072,1074,1076,1078,1080,1082,1084,1086],{"class":75,"line":110},[73,1050,121],{"class":120},[73,1052,124],{"class":87},[73,1054,127],{"class":120},[73,1056,124],{"class":87},[73,1058,229],{"class":120},[73,1060,124],{"class":87},[73,1062,234],{"class":137},[73,1064,98],{"class":141},[73,1066,145],{"class":144},[73,1068,1069],{"class":148},"GenerateManifestPlugin",[73,1071,145],{"class":144},[73,1073,154],{"class":87},[73,1075,157],{"class":87},[73,1077,249],{"class":101},[73,1079,154],{"class":87},[73,1081,254],{"class":101},[73,1083,105],{"class":87},[73,1085,165],{"class":79},[73,1087,88],{"class":87},[73,1089,1090,1093,1096,1098],{"class":75,"line":117},[73,1091,1092],{"class":79},"      const",[73,1094,1095],{"class":866}," manifest",[73,1097,940],{"class":391},[73,1099,88],{"class":87},[73,1101,1102,1105,1107,1110,1112,1115,1117],{"class":75,"line":170},[73,1103,1104],{"class":141},"        timestamp",[73,1106,858],{"class":87},[73,1108,1109],{"class":120}," Date",[73,1111,124],{"class":87},[73,1113,1114],{"class":137},"now",[73,1116,271],{"class":141},[73,1118,898],{"class":87},[73,1120,1121,1124,1126,1129,1131,1134,1136,1138,1140,1142,1144],{"class":75,"line":195},[73,1122,1123],{"class":141},"        files",[73,1125,858],{"class":87},[73,1127,1128],{"class":120}," Object",[73,1130,124],{"class":87},[73,1132,1133],{"class":137},"keys",[73,1135,98],{"class":141},[73,1137,249],{"class":120},[73,1139,124],{"class":87},[73,1141,832],{"class":120},[73,1143,105],{"class":141},[73,1145,898],{"class":87},[73,1147,1148],{"class":75,"line":205},[73,1149,1150],{"class":87},"      };\n",[73,1152,1153,1155,1158,1160,1162,1164,1166,1168,1171,1173,1177,1179,1182,1184],{"class":75,"line":212},[73,1154,1092],{"class":79},[73,1156,1157],{"class":866}," json",[73,1159,940],{"class":391},[73,1161,867],{"class":866},[73,1163,124],{"class":87},[73,1165,872],{"class":137},[73,1167,98],{"class":141},[73,1169,1170],{"class":120},"manifest",[73,1172,154],{"class":87},[73,1174,1176],{"class":1175},"s39Yj"," null",[73,1178,154],{"class":87},[73,1180,1181],{"class":317}," 2",[73,1183,105],{"class":141},[73,1185,192],{"class":87},[73,1187,1188,1191,1193,1195,1197,1199,1202,1204,1206,1208],{"class":75,"line":218},[73,1189,1190],{"class":120},"      compilation",[73,1192,124],{"class":87},[73,1194,832],{"class":120},[73,1196,835],{"class":141},[73,1198,145],{"class":144},[73,1200,1201],{"class":148},"manifest.json",[73,1203,145],{"class":144},[73,1205,845],{"class":141},[73,1207,848],{"class":391},[73,1209,88],{"class":87},[73,1211,1212,1215,1217,1219,1221,1223],{"class":75,"line":263},[73,1213,1214],{"class":137},"        source",[73,1216,858],{"class":87},[73,1218,861],{"class":87},[73,1220,165],{"class":79},[73,1222,1157],{"class":120},[73,1224,898],{"class":87},[73,1226,1227,1230,1232,1234,1236,1238,1240,1243],{"class":75,"line":278},[73,1228,1229],{"class":137},"        size",[73,1231,858],{"class":87},[73,1233,861],{"class":87},[73,1235,165],{"class":79},[73,1237,1157],{"class":120},[73,1239,124],{"class":87},[73,1241,1242],{"class":866},"length",[73,1244,898],{"class":87},[73,1246,1247],{"class":75,"line":301},[73,1248,1150],{"class":87},[73,1250,1251,1254,1256],{"class":75,"line":311},[73,1252,1253],{"class":137},"      callback",[73,1255,271],{"class":141},[73,1257,192],{"class":87},[73,1259,1260,1262,1264],{"class":75,"line":325},[73,1261,198],{"class":87},[73,1263,105],{"class":141},[73,1265,192],{"class":87},[73,1267,1268],{"class":75,"line":334},[73,1269,494],{"class":87},[73,1271,1272],{"class":75,"line":339},[73,1273,500],{"class":87},[555,1275,1277],{"id":1276},"_2-修改最终输出的-html配合-htmlwebpackplugin","2. 修改最终输出的 HTML（配合 HtmlWebpackPlugin）",[64,1279,1281],{"className":66,"code":1280,"language":68,"meta":69,"style":69},"class HtmlModifyPlugin {\n  apply(compiler) {\n    compiler.hooks.compilation.tap(\"HtmlModifyPlugin\", (compilation) => {\n      const HtmlWebpackPlugin = require(\"html-webpack-plugin\");\n      const hooks = HtmlWebpackPlugin.getHooks(compilation);\n      hooks.beforeEmit.tapAsync(\"HtmlModifyPlugin\", (data, cb) => {\n        data.html = data.html.replace(\u002F\u003Cbody>\u002F, '\u003Cbody>\u003Cdiv id=\"custom\">Inject\u003C\u002Fdiv>');\n        cb(null, data);\n      });\n    });\n  }\n}\n",[51,1282,1283,1292,1304,1341,1365,1389,1429,1478,1496,1504,1512,1516],{"__ignoreMap":69},[73,1284,1285,1287,1290],{"class":75,"line":76},[73,1286,80],{"class":79},[73,1288,1289],{"class":83}," HtmlModifyPlugin",[73,1291,88],{"class":87},[73,1293,1294,1296,1298,1300,1302],{"class":75,"line":91},[73,1295,95],{"class":94},[73,1297,98],{"class":87},[73,1299,102],{"class":101},[73,1301,105],{"class":87},[73,1303,88],{"class":87},[73,1305,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1327,1329,1331,1333,1335,1337,1339],{"class":75,"line":110},[73,1307,121],{"class":120},[73,1309,124],{"class":87},[73,1311,127],{"class":120},[73,1313,124],{"class":87},[73,1315,249],{"class":120},[73,1317,124],{"class":87},[73,1319,138],{"class":137},[73,1321,98],{"class":141},[73,1323,145],{"class":144},[73,1325,1326],{"class":148},"HtmlModifyPlugin",[73,1328,145],{"class":144},[73,1330,154],{"class":87},[73,1332,157],{"class":87},[73,1334,249],{"class":101},[73,1336,105],{"class":87},[73,1338,165],{"class":79},[73,1340,88],{"class":87},[73,1342,1343,1345,1348,1350,1352,1354,1356,1359,1361,1363],{"class":75,"line":117},[73,1344,1092],{"class":79},[73,1346,1347],{"class":866}," HtmlWebpackPlugin",[73,1349,940],{"class":391},[73,1351,943],{"class":137},[73,1353,98],{"class":141},[73,1355,145],{"class":144},[73,1357,1358],{"class":148},"html-webpack-plugin",[73,1360,145],{"class":144},[73,1362,105],{"class":141},[73,1364,192],{"class":87},[73,1366,1367,1369,1372,1374,1376,1378,1381,1383,1385,1387],{"class":75,"line":170},[73,1368,1092],{"class":79},[73,1370,1371],{"class":866}," hooks",[73,1373,940],{"class":391},[73,1375,1347],{"class":120},[73,1377,124],{"class":87},[73,1379,1380],{"class":137},"getHooks",[73,1382,98],{"class":141},[73,1384,249],{"class":120},[73,1386,105],{"class":141},[73,1388,192],{"class":87},[73,1390,1391,1394,1396,1399,1401,1403,1405,1407,1409,1411,1413,1415,1418,1420,1423,1425,1427],{"class":75,"line":195},[73,1392,1393],{"class":120},"      hooks",[73,1395,124],{"class":87},[73,1397,1398],{"class":120},"beforeEmit",[73,1400,124],{"class":87},[73,1402,234],{"class":137},[73,1404,98],{"class":141},[73,1406,145],{"class":144},[73,1408,1326],{"class":148},[73,1410,145],{"class":144},[73,1412,154],{"class":87},[73,1414,157],{"class":87},[73,1416,1417],{"class":101},"data",[73,1419,154],{"class":87},[73,1421,1422],{"class":101}," cb",[73,1424,105],{"class":87},[73,1426,165],{"class":79},[73,1428,88],{"class":87},[73,1430,1431,1434,1436,1439,1441,1444,1446,1448,1450,1453,1455,1457,1461,1463,1465,1468,1471,1474,1476],{"class":75,"line":205},[73,1432,1433],{"class":120},"        data",[73,1435,124],{"class":87},[73,1437,1438],{"class":120},"html",[73,1440,940],{"class":391},[73,1442,1443],{"class":120}," data",[73,1445,124],{"class":87},[73,1447,1438],{"class":120},[73,1449,124],{"class":87},[73,1451,1452],{"class":137},"replace",[73,1454,98],{"class":141},[73,1456,539],{"class":144},[73,1458,1460],{"class":1459},"sQRbd","\u003Cbody>",[73,1462,539],{"class":144},[73,1464,154],{"class":87},[73,1466,1467],{"class":144}," '",[73,1469,1470],{"class":148},"\u003Cbody>\u003Cdiv id=\"custom\">Inject\u003C\u002Fdiv>",[73,1472,1473],{"class":144},"'",[73,1475,105],{"class":141},[73,1477,192],{"class":87},[73,1479,1480,1483,1485,1488,1490,1492,1494],{"class":75,"line":212},[73,1481,1482],{"class":137},"        cb",[73,1484,98],{"class":141},[73,1486,1487],{"class":1175},"null",[73,1489,154],{"class":87},[73,1491,1443],{"class":120},[73,1493,105],{"class":141},[73,1495,192],{"class":87},[73,1497,1498,1500,1502],{"class":75,"line":218},[73,1499,475],{"class":87},[73,1501,105],{"class":141},[73,1503,192],{"class":87},[73,1505,1506,1508,1510],{"class":75,"line":263},[73,1507,198],{"class":87},[73,1509,105],{"class":141},[73,1511,192],{"class":87},[73,1513,1514],{"class":75,"line":278},[73,1515,494],{"class":87},[73,1517,1518],{"class":75,"line":301},[73,1519,500],{"class":87},[555,1521,1523],{"id":1522},"_3-打包后自动上传-cdn","3. 打包后自动上传 CDN",[64,1525,1527],{"className":66,"code":1526,"language":68,"meta":69,"style":69},"class UploadToCDNPlugin {\n  apply(compiler) {\n    compiler.hooks.afterEmit.tapPromise(\"UploadToCDNPlugin\", async (compilation) => {\n      const assets = compilation.assets;\n      for (const [filename, source] of Object.entries(assets)) {\n        const content = source.source();\n        \u002F\u002F 调用云存储 SDK 上传\n        await uploadToCDN(filename, content);\n      }\n    });\n  }\n}\n",[51,1528,1529,1538,1550,1591,1609,1653,1674,1679,1699,1704,1712,1716],{"__ignoreMap":69},[73,1530,1531,1533,1536],{"class":75,"line":76},[73,1532,80],{"class":79},[73,1534,1535],{"class":83}," UploadToCDNPlugin",[73,1537,88],{"class":87},[73,1539,1540,1542,1544,1546,1548],{"class":75,"line":91},[73,1541,95],{"class":94},[73,1543,98],{"class":87},[73,1545,102],{"class":101},[73,1547,105],{"class":87},[73,1549,88],{"class":87},[73,1551,1552,1554,1556,1558,1560,1563,1565,1567,1569,1571,1574,1576,1578,1581,1583,1585,1587,1589],{"class":75,"line":110},[73,1553,121],{"class":120},[73,1555,124],{"class":87},[73,1557,127],{"class":120},[73,1559,124],{"class":87},[73,1561,1562],{"class":120},"afterEmit",[73,1564,124],{"class":87},[73,1566,361],{"class":137},[73,1568,98],{"class":141},[73,1570,145],{"class":144},[73,1572,1573],{"class":148},"UploadToCDNPlugin",[73,1575,145],{"class":144},[73,1577,154],{"class":87},[73,1579,1580],{"class":79}," async",[73,1582,157],{"class":87},[73,1584,249],{"class":101},[73,1586,105],{"class":87},[73,1588,165],{"class":79},[73,1590,88],{"class":87},[73,1592,1593,1595,1598,1600,1603,1605,1607],{"class":75,"line":117},[73,1594,1092],{"class":79},[73,1596,1597],{"class":866}," assets",[73,1599,940],{"class":391},[73,1601,1602],{"class":120}," compilation",[73,1604,124],{"class":87},[73,1606,832],{"class":120},[73,1608,192],{"class":87},[73,1610,1611,1614,1616,1619,1622,1625,1627,1630,1633,1636,1638,1640,1643,1645,1647,1650],{"class":75,"line":170},[73,1612,1613],{"class":387},"      for",[73,1615,157],{"class":141},[73,1617,1618],{"class":79},"const",[73,1620,1621],{"class":87}," [",[73,1623,1624],{"class":866},"filename",[73,1626,154],{"class":87},[73,1628,1629],{"class":866}," source",[73,1631,1632],{"class":87},"]",[73,1634,1635],{"class":391}," of",[73,1637,1128],{"class":120},[73,1639,124],{"class":87},[73,1641,1642],{"class":137},"entries",[73,1644,98],{"class":141},[73,1646,832],{"class":120},[73,1648,1649],{"class":141},")) ",[73,1651,1652],{"class":87},"{\n",[73,1654,1655,1658,1661,1663,1665,1667,1670,1672],{"class":75,"line":195},[73,1656,1657],{"class":79},"        const",[73,1659,1660],{"class":866}," content",[73,1662,940],{"class":391},[73,1664,1629],{"class":120},[73,1666,124],{"class":87},[73,1668,1669],{"class":137},"source",[73,1671,271],{"class":141},[73,1673,192],{"class":87},[73,1675,1676],{"class":75,"line":205},[73,1677,1678],{"class":113},"        \u002F\u002F 调用云存储 SDK 上传\n",[73,1680,1681,1684,1687,1689,1691,1693,1695,1697],{"class":75,"line":212},[73,1682,1683],{"class":387},"        await",[73,1685,1686],{"class":137}," uploadToCDN",[73,1688,98],{"class":141},[73,1690,1624],{"class":120},[73,1692,154],{"class":87},[73,1694,1660],{"class":120},[73,1696,105],{"class":141},[73,1698,192],{"class":87},[73,1700,1701],{"class":75,"line":218},[73,1702,1703],{"class":87},"      }\n",[73,1705,1706,1708,1710],{"class":75,"line":263},[73,1707,198],{"class":87},[73,1709,105],{"class":141},[73,1711,192],{"class":87},[73,1713,1714],{"class":75,"line":278},[73,1715,494],{"class":87},[73,1717,1718],{"class":75,"line":301},[73,1719,500],{"class":87},[555,1721,1723],{"id":1722},"_4-移除指定注释内容","4. 移除指定注释内容",[64,1725,1727],{"className":66,"code":1726,"language":68,"meta":69,"style":69},"class RemoveCommentsPlugin {\n  apply(compiler) {\n    compiler.hooks.compilation.tap(\"RemoveCommentsPlugin\", (compilation) => {\n      \u002F\u002F 使用 TerserPlugin 的 hooks 或直接修改 assets\n      compilation.hooks.processAssets.tap(\n        {\n          name: \"RemoveCommentsPlugin\",\n          stage: compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,\n        },\n        (assets) => {\n          for (const [filename, source] of Object.entries(assets)) {\n            const content = source.source().toString();\n            const cleaned = content.replace(\u002F\\\u002F\\*.*?\\*\\\u002F\u002Fgs, \"\").replace(\u002F\\\u002F\\\u002F.*$\u002Fgm, \"\");\n            \u002F\u002F 更新 assets\n            compilation.updateAsset(filename, new RawSource(cleaned));\n          }\n        },\n      );\n    });\n  }\n}\n",[51,1728,1729,1738,1750,1787,1792,1812,1817,1832,1848,1853,1866,1901,1927,2004,2009,2039,2044,2048,2055,2063,2067],{"__ignoreMap":69},[73,1730,1731,1733,1736],{"class":75,"line":76},[73,1732,80],{"class":79},[73,1734,1735],{"class":83}," RemoveCommentsPlugin",[73,1737,88],{"class":87},[73,1739,1740,1742,1744,1746,1748],{"class":75,"line":91},[73,1741,95],{"class":94},[73,1743,98],{"class":87},[73,1745,102],{"class":101},[73,1747,105],{"class":87},[73,1749,88],{"class":87},[73,1751,1752,1754,1756,1758,1760,1762,1764,1766,1768,1770,1773,1775,1777,1779,1781,1783,1785],{"class":75,"line":110},[73,1753,121],{"class":120},[73,1755,124],{"class":87},[73,1757,127],{"class":120},[73,1759,124],{"class":87},[73,1761,249],{"class":120},[73,1763,124],{"class":87},[73,1765,138],{"class":137},[73,1767,98],{"class":141},[73,1769,145],{"class":144},[73,1771,1772],{"class":148},"RemoveCommentsPlugin",[73,1774,145],{"class":144},[73,1776,154],{"class":87},[73,1778,157],{"class":87},[73,1780,249],{"class":101},[73,1782,105],{"class":87},[73,1784,165],{"class":79},[73,1786,88],{"class":87},[73,1788,1789],{"class":75,"line":117},[73,1790,1791],{"class":113},"      \u002F\u002F 使用 TerserPlugin 的 hooks 或直接修改 assets\n",[73,1793,1794,1796,1798,1800,1802,1805,1807,1809],{"class":75,"line":170},[73,1795,1190],{"class":120},[73,1797,124],{"class":87},[73,1799,127],{"class":120},[73,1801,124],{"class":87},[73,1803,1804],{"class":120},"processAssets",[73,1806,124],{"class":87},[73,1808,138],{"class":137},[73,1810,1811],{"class":141},"(\n",[73,1813,1814],{"class":75,"line":195},[73,1815,1816],{"class":87},"        {\n",[73,1818,1819,1822,1824,1826,1828,1830],{"class":75,"line":205},[73,1820,1821],{"class":141},"          name",[73,1823,858],{"class":87},[73,1825,885],{"class":144},[73,1827,1772],{"class":148},[73,1829,145],{"class":144},[73,1831,898],{"class":87},[73,1833,1834,1837,1839,1841,1843,1846],{"class":75,"line":212},[73,1835,1836],{"class":141},"          stage",[73,1838,858],{"class":87},[73,1840,1602],{"class":120},[73,1842,124],{"class":87},[73,1844,1845],{"class":866},"PROCESS_ASSETS_STAGE_OPTIMIZE",[73,1847,898],{"class":87},[73,1849,1850],{"class":75,"line":218},[73,1851,1852],{"class":87},"        },\n",[73,1854,1855,1858,1860,1862,1864],{"class":75,"line":263},[73,1856,1857],{"class":87},"        (",[73,1859,832],{"class":101},[73,1861,105],{"class":87},[73,1863,165],{"class":79},[73,1865,88],{"class":87},[73,1867,1868,1871,1873,1875,1877,1879,1881,1883,1885,1887,1889,1891,1893,1895,1897,1899],{"class":75,"line":278},[73,1869,1870],{"class":387},"          for",[73,1872,157],{"class":141},[73,1874,1618],{"class":79},[73,1876,1621],{"class":87},[73,1878,1624],{"class":866},[73,1880,154],{"class":87},[73,1882,1629],{"class":866},[73,1884,1632],{"class":87},[73,1886,1635],{"class":391},[73,1888,1128],{"class":120},[73,1890,124],{"class":87},[73,1892,1642],{"class":137},[73,1894,98],{"class":141},[73,1896,832],{"class":120},[73,1898,1649],{"class":141},[73,1900,1652],{"class":87},[73,1902,1903,1906,1908,1910,1912,1914,1916,1918,1920,1923,1925],{"class":75,"line":301},[73,1904,1905],{"class":79},"            const",[73,1907,1660],{"class":866},[73,1909,940],{"class":391},[73,1911,1629],{"class":120},[73,1913,124],{"class":87},[73,1915,1669],{"class":137},[73,1917,271],{"class":141},[73,1919,124],{"class":87},[73,1921,1922],{"class":137},"toString",[73,1924,271],{"class":141},[73,1926,192],{"class":87},[73,1928,1929,1931,1934,1936,1938,1940,1942,1944,1946,1950,1953,1956,1959,1961,1965,1967,1970,1972,1974,1976,1978,1980,1983,1985,1988,1991,1993,1996,1998,2000,2002],{"class":75,"line":311},[73,1930,1905],{"class":79},[73,1932,1933],{"class":866}," cleaned",[73,1935,940],{"class":391},[73,1937,1660],{"class":120},[73,1939,124],{"class":87},[73,1941,1452],{"class":137},[73,1943,98],{"class":141},[73,1945,539],{"class":144},[73,1947,1949],{"class":1948},"sjYin","\\\u002F\\*",[73,1951,124],{"class":1952},"stzsN",[73,1954,1955],{"class":391},"*?",[73,1957,1958],{"class":1948},"\\*\\\u002F",[73,1960,539],{"class":144},[73,1962,1964],{"class":1963},"sw1J6","gs",[73,1966,154],{"class":87},[73,1968,1969],{"class":144}," \"\"",[73,1971,105],{"class":141},[73,1973,124],{"class":87},[73,1975,1452],{"class":137},[73,1977,98],{"class":141},[73,1979,539],{"class":144},[73,1981,1982],{"class":1948},"\\\u002F\\\u002F",[73,1984,124],{"class":1952},[73,1986,1987],{"class":391},"*",[73,1989,1990],{"class":387},"$",[73,1992,539],{"class":144},[73,1994,1995],{"class":1963},"gm",[73,1997,154],{"class":87},[73,1999,1969],{"class":144},[73,2001,105],{"class":141},[73,2003,192],{"class":87},[73,2005,2006],{"class":75,"line":325},[73,2007,2008],{"class":113},"            \u002F\u002F 更新 assets\n",[73,2010,2011,2014,2016,2019,2021,2023,2025,2027,2029,2031,2034,2037],{"class":75,"line":334},[73,2012,2013],{"class":120},"            compilation",[73,2015,124],{"class":87},[73,2017,2018],{"class":137},"updateAsset",[73,2020,98],{"class":141},[73,2022,1624],{"class":120},[73,2024,154],{"class":87},[73,2026,392],{"class":391},[73,2028,935],{"class":137},[73,2030,98],{"class":141},[73,2032,2033],{"class":120},"cleaned",[73,2035,2036],{"class":141},"))",[73,2038,192],{"class":87},[73,2040,2041],{"class":75,"line":339},[73,2042,2043],{"class":87},"          }\n",[73,2045,2046],{"class":75,"line":345},[73,2047,1852],{"class":87},[73,2049,2050,2053],{"class":75,"line":384},[73,2051,2052],{"class":141},"      )",[73,2054,192],{"class":87},[73,2056,2057,2059,2061],{"class":75,"line":412},[73,2058,198],{"class":87},[73,2060,105],{"class":141},[73,2062,192],{"class":87},[73,2064,2065],{"class":75,"line":426},[73,2066,494],{"class":87},[73,2068,2069],{"class":75,"line":449},[73,2070,500],{"class":87},[43,2072,2074,2075,2077],{"id":2073},"四使用-webpack-sources-处理代码字符串","四、使用 ",[51,2076,950],{}," 处理代码字符串",[23,2079,2080,2081,2083],{},"Webpack 内部使用 ",[51,2082,950],{}," 库来表示源代码，支持多种 Source 类型，可以进行拼接、修改、缓存等操作。",[566,2085,2086,2096],{},[569,2087,2088],{},[572,2089,2090,2093],{},[575,2091,2092],{},"Source 类型",[575,2094,2095],{},"用途",[585,2097,2098,2108,2118,2128],{},[572,2099,2100,2105],{},[590,2101,2102],{},[51,2103,2104],{},"RawSource",[590,2106,2107],{},"原始字符串内容",[572,2109,2110,2115],{},[590,2111,2112],{},[51,2113,2114],{},"ConcatSource",[590,2116,2117],{},"拼接多个 Source",[572,2119,2120,2125],{},[590,2121,2122],{},[51,2123,2124],{},"CachedSource",[590,2126,2127],{},"缓存内部 Source 结果，避免重复计算",[572,2129,2130,2135],{},[590,2131,2132],{},[51,2133,2134],{},"ReplaceSource",[590,2136,2137],{},"在原始内容中进行替换操作（保留 source map）",[23,2139,2140,2143],{},[27,2141,2142],{},"示例","：在生成的 JS 文件头部添加注释",[64,2145,2147],{"className":66,"code":2146,"language":68,"meta":69,"style":69},"const { RawSource, ConcatSource } = require(\"webpack-sources\");\n\nclass AddHeaderPlugin {\n  apply(compiler) {\n    compiler.hooks.emit.tapAsync(\"AddHeaderPlugin\", (compilation, callback) => {\n      const header = new RawSource(\"\u002F* This file generated by Webpack *\u002F\\n\");\n      for (const filename in compilation.assets) {\n        if (filename.endsWith(\".js\")) {\n          const original = compilation.assets[filename];\n          const combined = new ConcatSource(header, original);\n          compilation.assets[filename] = combined;\n        }\n      }\n      callback();\n    });\n  }\n}\n",[51,2148,2149,2180,2184,2193,2205,2246,2275,2300,2327,2351,2377,2398,2403,2407,2415,2423,2427],{"__ignoreMap":69},[73,2150,2151,2153,2155,2157,2159,2162,2164,2166,2168,2170,2172,2174,2176,2178],{"class":75,"line":76},[73,2152,1618],{"class":79},[73,2154,932],{"class":87},[73,2156,935],{"class":866},[73,2158,154],{"class":87},[73,2160,2161],{"class":866}," ConcatSource",[73,2163,893],{"class":87},[73,2165,940],{"class":391},[73,2167,943],{"class":137},[73,2169,98],{"class":120},[73,2171,145],{"class":144},[73,2173,950],{"class":148},[73,2175,145],{"class":144},[73,2177,105],{"class":120},[73,2179,192],{"class":87},[73,2181,2182],{"class":75,"line":91},[73,2183,209],{"emptyLinePlaceholder":208},[73,2185,2186,2188,2191],{"class":75,"line":110},[73,2187,80],{"class":79},[73,2189,2190],{"class":83}," AddHeaderPlugin",[73,2192,88],{"class":87},[73,2194,2195,2197,2199,2201,2203],{"class":75,"line":117},[73,2196,95],{"class":94},[73,2198,98],{"class":87},[73,2200,102],{"class":101},[73,2202,105],{"class":87},[73,2204,88],{"class":87},[73,2206,2207,2209,2211,2213,2215,2217,2219,2221,2223,2225,2228,2230,2232,2234,2236,2238,2240,2242,2244],{"class":75,"line":170},[73,2208,121],{"class":120},[73,2210,124],{"class":87},[73,2212,127],{"class":120},[73,2214,124],{"class":87},[73,2216,229],{"class":120},[73,2218,124],{"class":87},[73,2220,234],{"class":137},[73,2222,98],{"class":141},[73,2224,145],{"class":144},[73,2226,2227],{"class":148},"AddHeaderPlugin",[73,2229,145],{"class":144},[73,2231,154],{"class":87},[73,2233,157],{"class":87},[73,2235,249],{"class":101},[73,2237,154],{"class":87},[73,2239,254],{"class":101},[73,2241,105],{"class":87},[73,2243,165],{"class":79},[73,2245,88],{"class":87},[73,2247,2248,2250,2253,2255,2257,2259,2261,2263,2266,2269,2271,2273],{"class":75,"line":195},[73,2249,1092],{"class":79},[73,2251,2252],{"class":866}," header",[73,2254,940],{"class":391},[73,2256,392],{"class":391},[73,2258,935],{"class":137},[73,2260,98],{"class":141},[73,2262,145],{"class":144},[73,2264,2265],{"class":148},"\u002F* This file generated by Webpack *\u002F",[73,2267,2268],{"class":866},"\\n",[73,2270,145],{"class":144},[73,2272,105],{"class":141},[73,2274,192],{"class":87},[73,2276,2277,2279,2281,2283,2286,2289,2291,2293,2295,2298],{"class":75,"line":205},[73,2278,1613],{"class":387},[73,2280,157],{"class":141},[73,2282,1618],{"class":79},[73,2284,2285],{"class":866}," filename",[73,2287,2288],{"class":391}," in",[73,2290,1602],{"class":120},[73,2292,124],{"class":87},[73,2294,832],{"class":120},[73,2296,2297],{"class":141},") ",[73,2299,1652],{"class":87},[73,2301,2302,2305,2307,2309,2311,2314,2316,2318,2321,2323,2325],{"class":75,"line":212},[73,2303,2304],{"class":387},"        if",[73,2306,157],{"class":141},[73,2308,1624],{"class":120},[73,2310,124],{"class":87},[73,2312,2313],{"class":137},"endsWith",[73,2315,98],{"class":141},[73,2317,145],{"class":144},[73,2319,2320],{"class":148},".js",[73,2322,145],{"class":144},[73,2324,1649],{"class":141},[73,2326,1652],{"class":87},[73,2328,2329,2332,2335,2337,2339,2341,2343,2345,2347,2349],{"class":75,"line":218},[73,2330,2331],{"class":79},"          const",[73,2333,2334],{"class":866}," original",[73,2336,940],{"class":391},[73,2338,1602],{"class":120},[73,2340,124],{"class":87},[73,2342,832],{"class":120},[73,2344,835],{"class":141},[73,2346,1624],{"class":120},[73,2348,1632],{"class":141},[73,2350,192],{"class":87},[73,2352,2353,2355,2358,2360,2362,2364,2366,2369,2371,2373,2375],{"class":75,"line":263},[73,2354,2331],{"class":79},[73,2356,2357],{"class":866}," combined",[73,2359,940],{"class":391},[73,2361,392],{"class":391},[73,2363,2161],{"class":137},[73,2365,98],{"class":141},[73,2367,2368],{"class":120},"header",[73,2370,154],{"class":87},[73,2372,2334],{"class":120},[73,2374,105],{"class":141},[73,2376,192],{"class":87},[73,2378,2379,2382,2384,2386,2388,2390,2392,2394,2396],{"class":75,"line":278},[73,2380,2381],{"class":120},"          compilation",[73,2383,124],{"class":87},[73,2385,832],{"class":120},[73,2387,835],{"class":141},[73,2389,1624],{"class":120},[73,2391,845],{"class":141},[73,2393,848],{"class":391},[73,2395,2357],{"class":120},[73,2397,192],{"class":87},[73,2399,2400],{"class":75,"line":301},[73,2401,2402],{"class":87},"        }\n",[73,2404,2405],{"class":75,"line":311},[73,2406,1703],{"class":87},[73,2408,2409,2411,2413],{"class":75,"line":325},[73,2410,1253],{"class":137},[73,2412,271],{"class":141},[73,2414,192],{"class":87},[73,2416,2417,2419,2421],{"class":75,"line":334},[73,2418,198],{"class":87},[73,2420,105],{"class":141},[73,2422,192],{"class":87},[73,2424,2425],{"class":75,"line":339},[73,2426,494],{"class":87},[73,2428,2429],{"class":75,"line":345},[73,2430,500],{"class":87},[23,2432,2433,506],{},[27,2434,2435],{},"替换内容（保留 source map）",[64,2437,2439],{"className":66,"code":2438,"language":68,"meta":69,"style":69},"const { ReplaceSource } = require(\"webpack-sources\");\n\u002F\u002F 在某个 loader 内，也可在插件中使用\nconst replaceSource = new ReplaceSource(originalSource);\nreplaceSource.replace(0, 10, \"new content\");\nreplaceSource.insert(15, \"inserted\");\nconst result = replaceSource.source(); \u002F\u002F String\nresult.sourceAndMap; \u002F\u002F { source, map }\n",[51,2440,2441,2468,2473,2491,2523,2550,2573],{"__ignoreMap":69},[73,2442,2443,2445,2447,2450,2452,2454,2456,2458,2460,2462,2464,2466],{"class":75,"line":76},[73,2444,1618],{"class":79},[73,2446,932],{"class":87},[73,2448,2449],{"class":866}," ReplaceSource",[73,2451,893],{"class":87},[73,2453,940],{"class":391},[73,2455,943],{"class":137},[73,2457,98],{"class":120},[73,2459,145],{"class":144},[73,2461,950],{"class":148},[73,2463,145],{"class":144},[73,2465,105],{"class":120},[73,2467,192],{"class":87},[73,2469,2470],{"class":75,"line":91},[73,2471,2472],{"class":113},"\u002F\u002F 在某个 loader 内，也可在插件中使用\n",[73,2474,2475,2477,2480,2482,2484,2486,2489],{"class":75,"line":110},[73,2476,1618],{"class":79},[73,2478,2479],{"class":866}," replaceSource",[73,2481,940],{"class":391},[73,2483,392],{"class":391},[73,2485,2449],{"class":137},[73,2487,2488],{"class":120},"(originalSource)",[73,2490,192],{"class":87},[73,2492,2493,2496,2498,2500,2502,2505,2507,2510,2512,2514,2517,2519,2521],{"class":75,"line":117},[73,2494,2495],{"class":120},"replaceSource",[73,2497,124],{"class":87},[73,2499,1452],{"class":137},[73,2501,98],{"class":120},[73,2503,2504],{"class":317},"0",[73,2506,154],{"class":87},[73,2508,2509],{"class":317}," 10",[73,2511,154],{"class":87},[73,2513,885],{"class":144},[73,2515,2516],{"class":148},"new content",[73,2518,145],{"class":144},[73,2520,105],{"class":120},[73,2522,192],{"class":87},[73,2524,2525,2527,2529,2532,2534,2537,2539,2541,2544,2546,2548],{"class":75,"line":170},[73,2526,2495],{"class":120},[73,2528,124],{"class":87},[73,2530,2531],{"class":137},"insert",[73,2533,98],{"class":120},[73,2535,2536],{"class":317},"15",[73,2538,154],{"class":87},[73,2540,885],{"class":144},[73,2542,2543],{"class":148},"inserted",[73,2545,145],{"class":144},[73,2547,105],{"class":120},[73,2549,192],{"class":87},[73,2551,2552,2554,2557,2559,2561,2563,2565,2567,2570],{"class":75,"line":195},[73,2553,1618],{"class":79},[73,2555,2556],{"class":866}," result",[73,2558,940],{"class":391},[73,2560,2479],{"class":120},[73,2562,124],{"class":87},[73,2564,1669],{"class":137},[73,2566,271],{"class":120},[73,2568,2569],{"class":87},";",[73,2571,2572],{"class":113}," \u002F\u002F String\n",[73,2574,2575,2578,2580,2583,2585],{"class":75,"line":205},[73,2576,2577],{"class":120},"result",[73,2579,124],{"class":87},[73,2581,2582],{"class":120},"sourceAndMap",[73,2584,2569],{"class":87},[73,2586,2587],{"class":113}," \u002F\u002F { source, map }\n",[43,2589,2591],{"id":2590},"五node-调试-webpack-插件","五、Node 调试 Webpack 插件",[23,2593,2594],{},"使用 Chrome DevTools 可以断点调试插件代码。",[555,2596,2598],{"id":2597},"_1-方法一命令行启动","1. 方法一：命令行启动",[64,2600,2604],{"className":2601,"code":2602,"language":2603,"meta":69,"style":69},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","node --inspect-brk .\u002Fnode_modules\u002Fwebpack\u002Fbin\u002Fwebpack.js --config webpack.config.js\n","bash",[51,2605,2606],{"__ignoreMap":69},[73,2607,2608,2611,2614,2617,2620],{"class":75,"line":76},[73,2609,2610],{"class":83},"node",[73,2612,2613],{"class":1952}," --inspect-brk",[73,2615,2616],{"class":148}," .\u002Fnode_modules\u002Fwebpack\u002Fbin\u002Fwebpack.js",[73,2618,2619],{"class":1952}," --config",[73,2621,2622],{"class":148}," webpack.config.js\n",[508,2624,2625,2631],{},[511,2626,2627,2630],{},[51,2628,2629],{},"--inspect-brk","：在第一行代码处断点，等待调试器连接。",[511,2632,2633,2634,2637],{},"打开 Chrome 浏览器，访问 ",[51,2635,2636],{},"chrome:\u002F\u002Finspect","，点击「Open dedicated DevTools for Node」。",[555,2639,2641],{"id":2640},"_2-方法二vs-code-调试配置","2. 方法二：VS Code 调试配置",[23,2643,2644,2645,2648],{},"在 ",[51,2646,2647],{},".vscode\u002Flaunch.json"," 中添加：",[64,2650,2654],{"className":2651,"code":2652,"language":2653,"meta":69,"style":69},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"node\",\n      \"request\": \"launch\",\n      \"name\": \"Debug Webpack\",\n      \"cwd\": \"${workspaceFolder}\",\n      \"runtimeExecutable\": \"node\",\n      \"args\": [\n        \"--inspect-brk\",\n        \".\u002Fnode_modules\u002Fwebpack\u002Fbin\u002Fwebpack.js\",\n        \"--config\",\n        \"webpack.config.js\"\n      ]\n    }\n  ]\n}\n","json",[51,2655,2656,2660,2682,2696,2701,2721,2741,2761,2781,2800,2813,2824,2835,2846,2856,2861,2866,2871],{"__ignoreMap":69},[73,2657,2658],{"class":75,"line":76},[73,2659,1652],{"class":87},[73,2661,2662,2665,2669,2671,2673,2675,2678,2680],{"class":75,"line":91},[73,2663,2664],{"class":1175},"  \"",[73,2666,2668],{"class":2667},"sseR_","version",[73,2670,145],{"class":1175},[73,2672,858],{"class":87},[73,2674,885],{"class":144},[73,2676,2677],{"class":148},"0.2.0",[73,2679,145],{"class":144},[73,2681,898],{"class":87},[73,2683,2684,2686,2689,2691,2693],{"class":75,"line":110},[73,2685,2664],{"class":1175},[73,2687,2688],{"class":2667},"configurations",[73,2690,145],{"class":1175},[73,2692,858],{"class":87},[73,2694,2695],{"class":87}," [\n",[73,2697,2698],{"class":75,"line":117},[73,2699,2700],{"class":87},"    {\n",[73,2702,2703,2706,2709,2711,2713,2715,2717,2719],{"class":75,"line":170},[73,2704,2705],{"class":1175},"      \"",[73,2707,2708],{"class":395},"type",[73,2710,145],{"class":1175},[73,2712,858],{"class":87},[73,2714,885],{"class":144},[73,2716,2610],{"class":148},[73,2718,145],{"class":144},[73,2720,898],{"class":87},[73,2722,2723,2725,2728,2730,2732,2734,2737,2739],{"class":75,"line":195},[73,2724,2705],{"class":1175},[73,2726,2727],{"class":395},"request",[73,2729,145],{"class":1175},[73,2731,858],{"class":87},[73,2733,885],{"class":144},[73,2735,2736],{"class":148},"launch",[73,2738,145],{"class":144},[73,2740,898],{"class":87},[73,2742,2743,2745,2748,2750,2752,2754,2757,2759],{"class":75,"line":205},[73,2744,2705],{"class":1175},[73,2746,2747],{"class":395},"name",[73,2749,145],{"class":1175},[73,2751,858],{"class":87},[73,2753,885],{"class":144},[73,2755,2756],{"class":148},"Debug Webpack",[73,2758,145],{"class":144},[73,2760,898],{"class":87},[73,2762,2763,2765,2768,2770,2772,2774,2777,2779],{"class":75,"line":212},[73,2764,2705],{"class":1175},[73,2766,2767],{"class":395},"cwd",[73,2769,145],{"class":1175},[73,2771,858],{"class":87},[73,2773,885],{"class":144},[73,2775,2776],{"class":148},"${workspaceFolder}",[73,2778,145],{"class":144},[73,2780,898],{"class":87},[73,2782,2783,2785,2788,2790,2792,2794,2796,2798],{"class":75,"line":218},[73,2784,2705],{"class":1175},[73,2786,2787],{"class":395},"runtimeExecutable",[73,2789,145],{"class":1175},[73,2791,858],{"class":87},[73,2793,885],{"class":144},[73,2795,2610],{"class":148},[73,2797,145],{"class":144},[73,2799,898],{"class":87},[73,2801,2802,2804,2807,2809,2811],{"class":75,"line":263},[73,2803,2705],{"class":1175},[73,2805,2806],{"class":395},"args",[73,2808,145],{"class":1175},[73,2810,858],{"class":87},[73,2812,2695],{"class":87},[73,2814,2815,2818,2820,2822],{"class":75,"line":278},[73,2816,2817],{"class":144},"        \"",[73,2819,2629],{"class":148},[73,2821,145],{"class":144},[73,2823,898],{"class":87},[73,2825,2826,2828,2831,2833],{"class":75,"line":301},[73,2827,2817],{"class":144},[73,2829,2830],{"class":148},".\u002Fnode_modules\u002Fwebpack\u002Fbin\u002Fwebpack.js",[73,2832,145],{"class":144},[73,2834,898],{"class":87},[73,2836,2837,2839,2842,2844],{"class":75,"line":311},[73,2838,2817],{"class":144},[73,2840,2841],{"class":148},"--config",[73,2843,145],{"class":144},[73,2845,898],{"class":87},[73,2847,2848,2850,2853],{"class":75,"line":325},[73,2849,2817],{"class":144},[73,2851,2852],{"class":148},"webpack.config.js",[73,2854,2855],{"class":144},"\"\n",[73,2857,2858],{"class":75,"line":334},[73,2859,2860],{"class":87},"      ]\n",[73,2862,2863],{"class":75,"line":339},[73,2864,2865],{"class":87},"    }\n",[73,2867,2868],{"class":75,"line":345},[73,2869,2870],{"class":87},"  ]\n",[73,2872,2873],{"class":75,"line":384},[73,2874,500],{"class":87},[23,2876,2877],{},"然后在插件代码中直接打断点即可。",[555,2879,2881],{"id":2880},"_3-调试技巧","3. 调试技巧",[508,2883,2884,2894,2901],{},[511,2885,2886,2887,2889,2890,2893],{},"在插件的 ",[51,2888,57],{}," 方法内设置 ",[51,2891,2892],{},"debugger"," 语句。",[511,2895,2896,2897,2900],{},"使用 ",[51,2898,2899],{},"console.log(compiler.hooks)"," 查看可用的钩子和参数。",[511,2902,2903,2904,2906,2907,2909],{},"通过 ",[51,2905,594],{}," 和 ",[51,2908,711],{}," 检查当前状态。",[2911,2912,2913],"h2",{"id":2913},"总结",[566,2915,2916,2926],{},[569,2917,2918],{},[572,2919,2920,2923],{},[575,2921,2922],{},"方面",[575,2924,2925],{},"要点",[585,2927,2928,2946,2956,2976,2986,3000],{},[572,2929,2930,2935],{},[590,2931,2932],{},[27,2933,2934],{},"基本架构",[590,2936,2937,2939,2940,539,2942,539,2944,614],{},[51,2938,53],{}," + 钩子注册（",[51,2941,138],{},[51,2943,234],{},[51,2945,361],{},[572,2947,2948,2953],{},[590,2949,2950],{},[27,2951,2952],{},"Compiler",[590,2954,2955],{},"全局单例，包含配置、文件系统、生命周期钩子",[572,2957,2958,2963],{},[590,2959,2960],{},[27,2961,2962],{},"Compilation",[590,2964,2965,2966,2969,2970,2969,2973,2975],{},"每次构建的上下文，包含 ",[51,2967,2968],{},"modules","、",[51,2971,2972],{},"chunks",[51,2974,832],{},"（关键修改点）",[572,2977,2978,2983],{},[590,2979,2980],{},[27,2981,2982],{},"常见插件",[590,2984,2985],{},"生成额外文件、修改 HTML、上传 CDN、移除注释等",[572,2987,2988,2992],{},[590,2989,2990],{},[27,2991,950],{},[590,2993,2994,2969,2996,2969,2998,2077],{},[51,2995,2104],{},[51,2997,2114],{},[51,2999,2134],{},[572,3001,3002,3007],{},[590,3003,3004],{},[27,3005,3006],{},"调试",[590,3008,3009,3011],{},[51,3010,2629],{}," + Chrome DevTools 或 VS Code 启动配置",[23,3013,3014,3015,3017,3018,3020,3021,3023],{},"开发高级插件时，注意钩子的执行时机（",[51,3016,229],{}," 适合修改最终资源，",[51,3019,1804],{}," 是 Webpack 5 推荐的资源处理阶段），并合理使用 ",[51,3022,950],{}," 保证 source map 支持。",[2911,3025,3026],{"id":3026},"参考文献",[23,3028,3029],{},"以下链接在编写时均可正常访问：",[566,3031,3032,3041],{},[569,3033,3034],{},[572,3035,3036,3039],{},[575,3037,3038],{},"资料",[575,3040,580],{},[585,3042,3043,3056],{},[572,3044,3045,3053],{},[590,3046,3047],{},[32,3048,3052],{"href":3049,"rel":3050},"https:\u002F\u002Fwebpack.js.org\u002Fapi\u002Fplugins\u002F",[3051],"nofollow","Plugin API",[590,3054,3055],{},"官方",[572,3057,3058,3065],{},[590,3059,3060],{},[32,3061,3064],{"href":3062,"rel":3063},"https:\u002F\u002Fwebpack.js.org\u002Fcontribute\u002Fwriting-a-plugin\u002F",[3051],"编写 Plugin",[590,3066,3067],{},"指南",[3069,3070,3071],"style",{},"html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--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 .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 .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--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 .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--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 .sQRbd, html code.shiki .sQRbd{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#DBEDFF}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 .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":69,"searchDepth":91,"depth":91,"links":3073},[3074,3075,3076,3077,3079,3080,3081],{"id":45,"depth":110,"text":46},{"id":552,"depth":110,"text":553},{"id":1015,"depth":110,"text":1016},{"id":2073,"depth":110,"text":3078},"四、使用 webpack-sources 处理代码字符串",{"id":2590,"depth":110,"text":2591},{"id":2913,"depth":91,"text":2913},{"id":3026,"depth":91,"text":3026},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fplugin","knowledge\u002Fknowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Fplugin.md","md",{"items":3087},[3088,3090,3094,3098,3100,3104],{"path":34,"title":35,"description":3089,"category":10,"score":195},"Webpack 是静态模块打包器：从入口递归解析依赖，经 Loader 转换后输出一个或多个 bundle。与 Vite 对比见 Webpack 与 Vite。",{"path":3091,"title":3092,"description":3093,"category":10,"score":195},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks","产物优化","Webpack 通过代码分割、Tree Shaking、压缩与资源模块等减少体积、改善缓存。原理背景见 工作原理。",{"path":3095,"title":3096,"description":3097,"category":10,"score":195},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fcompany","企业级实践","大型前端项目在 Webpack 场景下的多环境拆分、Docker 构建缓存、自定义 CLI 与微前端（Module Federation \u002F single-spa）等实践。入门见 工程化概览。",{"path":39,"title":40,"description":3099,"category":10,"score":195},"Loader 在 Webpack 构建链中把源文件转为可打包的 JS 模块（如 TS、SCSS、Vue SFC）。见 工作原理。",{"path":3101,"title":3102,"description":3103,"category":10,"score":195},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fadvanced","进阶配置","Webpack 进阶场景：多页面（MPA）、devServer、环境变量注入、Source Map、Module Federation 等。基础见 工作原理。",{"path":3105,"title":3106,"description":3107,"category":10,"score":117},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fplugin","插件开发","Vite 插件兼容 Rollup 插件，并扩展 config、configureServer、transformIndexHtml 等钩子。原理见 工作原理。",{"series":3109,"title":12,"items":3110,"index":117,"prev":3122,"next":3123},"booklet\u002Fproject\u002Fwebpack",[3111,3113,3115,3117,3119,3120],{"path":3101,"title":3102,"date":3112,"pinned":15},"2021-10-18",{"path":3091,"title":3092,"date":3114,"pinned":15},"2025-01-28",{"path":3095,"title":3096,"date":3116,"pinned":15},"2024-07-30",{"path":39,"title":40,"date":3118,"pinned":15},"2022-11-14",{"path":7,"title":8,"date":14,"pinned":15},{"path":34,"title":35,"date":3121,"pinned":15},"2025-12-19",{"path":39,"title":40,"date":3118,"pinned":15},{"path":34,"title":35,"date":3121,"pinned":15}]