[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader":2427,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader":2451},{"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":2423,"stem":2424,"id":2425,"extension":2426},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Floader","Loader","Loader 在 Webpack 构建链中把源文件转为可打包的 JS 模块（如 TS、SCSS、Vue SFC）。见 工作原理。","技能小册",[12,13],"webpack","loader","2022-11-14",false,{"type":17,"value":18,"toc":2414},"minimark",[19,22,35,40,52,57,60,179,189,196,202,210,247,250,406,415,419,422,442,466,470,473,477,484,599,606,692,697,723,727,734,864,868,888,892,899,902,1154,1197,1203,1206,1415,1419,1423,1430,1525,1529,1536,1834,1838,1982,1988,1992,2011,2015,2022,2051,2055,2061,2091,2094,2100,2104,2130,2133,2237,2241,2260,2264,2357,2366,2369,2372,2410],[20,21,8],"h1",{"id":13},[23,24,25,28,29,34],"p",{},[26,27,8],"strong",{}," 在 Webpack 构建链中把源文件转为可打包的 JS 模块（如 TS、SCSS、Vue SFC）。见 ",[30,31,33],"a",{"href":32},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fworkflow","工作原理","。",[36,37,39],"h3",{"id":38},"一loader-执行顺序","一、Loader 执行顺序",[23,41,42,43,46,47,51],{},"Loader 的执行顺序遵循 ",[26,44,45],{},"从右向左、从下到上"," 的原则，但通过 ",[48,49,50],"code",{},"enforce"," 可以改变优先级。",[53,54,56],"h4",{"id":55},"_1-默认顺序normal-loader","1. 默认顺序（normal loader）",[23,58,59],{},"在配置数组中，Loader 从后往前执行（类似洋葱模型）。例如：",[61,62,67],"pre",{"className":63,"code":64,"language":65,"meta":66,"style":66},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","module: {\n  rules: [{ test: \u002F\\.js$\u002F, use: [\"loader-c\", \"loader-b\", \"loader-a\"] }];\n}\n","js","",[48,68,69,85,173],{"__ignoreMap":66},[70,71,74,78,82],"span",{"class":72,"line":73},"line",1,[70,75,77],{"class":76},"sbgvK","module",[70,79,81],{"class":80},"sP7_E",":",[70,83,84],{"class":80}," {\n",[70,86,88,91,93,97,100,103,105,109,113,116,120,123,126,129,131,133,136,140,142,144,147,150,152,154,156,159,161,164,167,170],{"class":72,"line":87},2,[70,89,90],{"class":76},"  rules",[70,92,81],{"class":80},[70,94,96],{"class":95},"skxfh"," [",[70,98,99],{"class":80},"{",[70,101,102],{"class":95}," test",[70,104,81],{"class":80},[70,106,108],{"class":107},"sjJ54"," \u002F",[70,110,112],{"class":111},"sjYin","\\.",[70,114,65],{"class":115},"sQRbd",[70,117,119],{"class":118},"sVHd0","$",[70,121,122],{"class":107},"\u002F",[70,124,125],{"class":80},",",[70,127,128],{"class":95}," use",[70,130,81],{"class":80},[70,132,96],{"class":95},[70,134,135],{"class":107},"\"",[70,137,139],{"class":138},"s_sjI","loader-c",[70,141,135],{"class":107},[70,143,125],{"class":80},[70,145,146],{"class":107}," \"",[70,148,149],{"class":138},"loader-b",[70,151,135],{"class":107},[70,153,125],{"class":80},[70,155,146],{"class":107},[70,157,158],{"class":138},"loader-a",[70,160,135],{"class":107},[70,162,163],{"class":95},"] ",[70,165,166],{"class":80},"}",[70,168,169],{"class":95},"]",[70,171,172],{"class":80},";\n",[70,174,176],{"class":72,"line":175},3,[70,177,178],{"class":80},"}\n",[23,180,181,182,184,185,184,187,34],{},"执行顺序：",[48,183,158],{}," → ",[48,186,149],{},[48,188,139],{},[53,190,192,193,195],{"id":191},"_2-enforce-分类","2. ",[48,194,50],{}," 分类",[23,197,198,199,201],{},"可以为 Loader 指定 ",[48,200,50],{}," 属性，分为四类，执行顺序为：",[61,203,208],{"className":204,"code":206,"language":207},[205],"language-text","pre → normal → inline → post\n","text",[48,209,206],{"__ignoreMap":66},[211,212,213,223,229,238],"ul",{},[214,215,216,218,219,222],"li",{},[26,217,61],{},"：前置 loader（",[48,220,221],{},"enforce: 'pre'","）",[214,224,225,228],{},[26,226,227],{},"normal","：普通 loader（默认）",[214,230,231,234,235,222],{},[26,232,233],{},"inline","：内联 loader（在 import 语句中直接使用，如 ",[48,236,237],{},"import '!style-loader!css-loader!.\u002Fa.css'",[214,239,240,243,244,222],{},[26,241,242],{},"post","：后置 loader（",[48,245,246],{},"enforce: 'post'",[23,248,249],{},"示例：",[61,251,253],{"className":63,"code":252,"language":65,"meta":66,"style":66},"rules: [\n  { test: \u002F\\.js$\u002F, loader: \"pre-loader\", enforce: \"pre\" },\n  { test: \u002F\\.js$\u002F, loader: \"normal-loader\" }, \u002F\u002F enforce 默认 'normal'\n  { test: \u002F\\.js$\u002F, loader: \"post-loader\", enforce: \"post\" },\n];\n",[48,254,255,266,315,353,399],{"__ignoreMap":66},[70,256,257,260,262],{"class":72,"line":73},[70,258,259],{"class":76},"rules",[70,261,81],{"class":80},[70,263,265],{"class":264},"su5hD"," [\n",[70,267,268,271,273,275,277,279,281,283,285,287,290,292,294,297,299,301,304,306,308,310,312],{"class":72,"line":87},[70,269,270],{"class":80},"  {",[70,272,102],{"class":95},[70,274,81],{"class":80},[70,276,108],{"class":107},[70,278,112],{"class":111},[70,280,65],{"class":115},[70,282,119],{"class":118},[70,284,122],{"class":107},[70,286,125],{"class":80},[70,288,289],{"class":95}," loader",[70,291,81],{"class":80},[70,293,146],{"class":107},[70,295,296],{"class":138},"pre-loader",[70,298,135],{"class":107},[70,300,125],{"class":80},[70,302,303],{"class":95}," enforce",[70,305,81],{"class":80},[70,307,146],{"class":107},[70,309,61],{"class":138},[70,311,135],{"class":107},[70,313,314],{"class":80}," },\n",[70,316,317,319,321,323,325,327,329,331,333,335,337,339,341,344,346,349],{"class":72,"line":175},[70,318,270],{"class":80},[70,320,102],{"class":95},[70,322,81],{"class":80},[70,324,108],{"class":107},[70,326,112],{"class":111},[70,328,65],{"class":115},[70,330,119],{"class":118},[70,332,122],{"class":107},[70,334,125],{"class":80},[70,336,289],{"class":95},[70,338,81],{"class":80},[70,340,146],{"class":107},[70,342,343],{"class":138},"normal-loader",[70,345,135],{"class":107},[70,347,348],{"class":80}," },",[70,350,352],{"class":351},"sutJx"," \u002F\u002F enforce 默认 'normal'\n",[70,354,356,358,360,362,364,366,368,370,372,374,376,378,380,383,385,387,389,391,393,395,397],{"class":72,"line":355},4,[70,357,270],{"class":80},[70,359,102],{"class":95},[70,361,81],{"class":80},[70,363,108],{"class":107},[70,365,112],{"class":111},[70,367,65],{"class":115},[70,369,119],{"class":118},[70,371,122],{"class":107},[70,373,125],{"class":80},[70,375,289],{"class":95},[70,377,81],{"class":80},[70,379,146],{"class":107},[70,381,382],{"class":138},"post-loader",[70,384,135],{"class":107},[70,386,125],{"class":80},[70,388,303],{"class":95},[70,390,81],{"class":80},[70,392,146],{"class":107},[70,394,242],{"class":138},[70,396,135],{"class":107},[70,398,314],{"class":80},[70,400,402,404],{"class":72,"line":401},5,[70,403,169],{"class":264},[70,405,172],{"class":80},[23,407,181,408,184,410,184,412,414],{},[48,409,296],{},[48,411,343],{},[48,413,382],{},"。如果有内联 loader，会在 normal 之后、post 之前执行。",[53,416,418],{"id":417},"_3-内联-loader-的覆盖符号","3. 内联 loader 的覆盖符号",[23,420,421],{},"在 import 语句中，可以使用前缀改变 loader 执行顺序：",[211,423,424,430,436],{},[214,425,426,429],{},[48,427,428],{},"!"," 禁用 normal loader",[214,431,432,435],{},[48,433,434],{},"-!"," 禁用 pre 和 normal loader",[214,437,438,441],{},[48,439,440],{},"!!"," 禁用所有除了内联 loader",[61,443,445],{"className":63,"code":444,"language":65,"meta":66,"style":66},"\u002F\u002F 只使用 style-loader 和 css-loader，跳过 pre\u002Fnormal\u002Fpost\nimport \"!!style-loader!css-loader!.\u002Fa.css\";\n",[48,446,447,452],{"__ignoreMap":66},[70,448,449],{"class":72,"line":73},[70,450,451],{"class":351},"\u002F\u002F 只使用 style-loader 和 css-loader，跳过 pre\u002Fnormal\u002Fpost\n",[70,453,454,457,459,462,464],{"class":72,"line":87},[70,455,456],{"class":118},"import",[70,458,146],{"class":107},[70,460,461],{"class":138},"!!style-loader!css-loader!.\u002Fa.css",[70,463,135],{"class":107},[70,465,172],{"class":80},[36,467,469],{"id":468},"二loader-的输入与输出","二、Loader 的输入与输出",[23,471,472],{},"Loader 接收文件内容（字符串或 Buffer），返回转换后的内容。",[53,474,476],{"id":475},"_1-同步-loader","1. 同步 Loader",[23,478,479,480,483],{},"直接 ",[48,481,482],{},"return"," 转换后的内容。",[61,485,487],{"className":63,"code":486,"language":65,"meta":66,"style":66},"module.exports = function (source) {\n  \u002F\u002F source 是原始文件内容\n  const result = source.replace(\u002Fconsole\\.log\\(.*?\\)\u002Fg, \"\");\n  return result;\n};\n",[48,488,489,520,525,585,594],{"__ignoreMap":66},[70,490,491,494,497,500,504,508,511,515,518],{"class":72,"line":73},[70,492,77],{"class":493},"s39Yj",[70,495,496],{"class":80},".",[70,498,499],{"class":493},"exports",[70,501,503],{"class":502},"smGrS"," =",[70,505,507],{"class":506},"sbsja"," function",[70,509,510],{"class":80}," (",[70,512,514],{"class":513},"s99_P","source",[70,516,517],{"class":80},")",[70,519,84],{"class":80},[70,521,522],{"class":72,"line":87},[70,523,524],{"class":351},"  \u002F\u002F source 是原始文件内容\n",[70,526,527,530,534,536,539,541,545,548,550,553,555,558,561,564,567,570,572,576,578,581,583],{"class":72,"line":175},[70,528,529],{"class":506},"  const",[70,531,533],{"class":532},"s_hVV"," result",[70,535,503],{"class":502},[70,537,538],{"class":264}," source",[70,540,496],{"class":80},[70,542,544],{"class":543},"sGLFI","replace",[70,546,547],{"class":95},"(",[70,549,122],{"class":107},[70,551,552],{"class":115},"console",[70,554,112],{"class":111},[70,556,557],{"class":115},"log",[70,559,560],{"class":111},"\\(",[70,562,496],{"class":563},"stzsN",[70,565,566],{"class":502},"*?",[70,568,569],{"class":111},"\\)",[70,571,122],{"class":107},[70,573,575],{"class":574},"sw1J6","g",[70,577,125],{"class":80},[70,579,580],{"class":107}," \"\"",[70,582,517],{"class":95},[70,584,172],{"class":80},[70,586,587,590,592],{"class":72,"line":355},[70,588,589],{"class":118},"  return",[70,591,533],{"class":264},[70,593,172],{"class":80},[70,595,596],{"class":72,"line":401},[70,597,598],{"class":80},"};\n",[23,600,601,602,605],{},"也可以使用 ",[48,603,604],{},"this.callback"," 返回多个值：",[61,607,609],{"className":63,"code":608,"language":65,"meta":66,"style":66},"module.exports = function (source) {\n  const result = process(source);\n  this.callback(null, result, sourceMap, meta);\n  \u002F\u002F 不返回值 (return;)\n};\n",[48,610,611,631,650,683,688],{"__ignoreMap":66},[70,612,613,615,617,619,621,623,625,627,629],{"class":72,"line":73},[70,614,77],{"class":493},[70,616,496],{"class":80},[70,618,499],{"class":493},[70,620,503],{"class":502},[70,622,507],{"class":506},[70,624,510],{"class":80},[70,626,514],{"class":513},[70,628,517],{"class":80},[70,630,84],{"class":80},[70,632,633,635,637,639,642,644,646,648],{"class":72,"line":87},[70,634,529],{"class":506},[70,636,533],{"class":532},[70,638,503],{"class":502},[70,640,641],{"class":543}," process",[70,643,547],{"class":95},[70,645,514],{"class":264},[70,647,517],{"class":95},[70,649,172],{"class":80},[70,651,652,655,657,660,662,665,667,669,671,674,676,679,681],{"class":72,"line":175},[70,653,654],{"class":493},"  this",[70,656,496],{"class":80},[70,658,659],{"class":543},"callback",[70,661,547],{"class":95},[70,663,664],{"class":493},"null",[70,666,125],{"class":80},[70,668,533],{"class":264},[70,670,125],{"class":80},[70,672,673],{"class":264}," sourceMap",[70,675,125],{"class":80},[70,677,678],{"class":264}," meta",[70,680,517],{"class":95},[70,682,172],{"class":80},[70,684,685],{"class":72,"line":355},[70,686,687],{"class":351},"  \u002F\u002F 不返回值 (return;)\n",[70,689,690],{"class":72,"line":401},[70,691,598],{"class":80},[23,693,694,696],{},[48,695,604],{}," 参数：",[211,698,699,705,711,717],{},[214,700,701,704],{},[48,702,703],{},"error","：Error 或 null",[214,706,707,710],{},[48,708,709],{},"content","：转换后的代码（String 或 Buffer）",[214,712,713,716],{},[48,714,715],{},"sourceMap","：可选的 source map",[214,718,719,722],{},[48,720,721],{},"meta","：可选的元数据（如 AST 等）",[53,724,726],{"id":725},"_2-异步-loader","2. 异步 Loader",[23,728,729,730,733],{},"使用 ",[48,731,732],{},"this.async()"," 获取一个回调函数。",[61,735,737],{"className":63,"code":736,"language":65,"meta":66,"style":66},"module.exports = function (source) {\n  const callback = this.async();\n  someAsyncProcess(source, (err, result) => {\n    if (err) return callback(err);\n    callback(null, result);\n  });\n};\n",[48,738,739,759,781,808,832,849,859],{"__ignoreMap":66},[70,740,741,743,745,747,749,751,753,755,757],{"class":72,"line":73},[70,742,77],{"class":493},[70,744,496],{"class":80},[70,746,499],{"class":493},[70,748,503],{"class":502},[70,750,507],{"class":506},[70,752,510],{"class":80},[70,754,514],{"class":513},[70,756,517],{"class":80},[70,758,84],{"class":80},[70,760,761,763,766,768,771,773,776,779],{"class":72,"line":87},[70,762,529],{"class":506},[70,764,765],{"class":532}," callback",[70,767,503],{"class":502},[70,769,770],{"class":493}," this",[70,772,496],{"class":80},[70,774,775],{"class":543},"async",[70,777,778],{"class":95},"()",[70,780,172],{"class":80},[70,782,783,786,788,790,792,794,797,799,801,803,806],{"class":72,"line":175},[70,784,785],{"class":543},"  someAsyncProcess",[70,787,547],{"class":95},[70,789,514],{"class":264},[70,791,125],{"class":80},[70,793,510],{"class":80},[70,795,796],{"class":513},"err",[70,798,125],{"class":80},[70,800,533],{"class":513},[70,802,517],{"class":80},[70,804,805],{"class":506}," =>",[70,807,84],{"class":80},[70,809,810,813,815,817,820,822,824,826,828,830],{"class":72,"line":355},[70,811,812],{"class":118},"    if",[70,814,510],{"class":95},[70,816,796],{"class":264},[70,818,819],{"class":95},") ",[70,821,482],{"class":118},[70,823,765],{"class":543},[70,825,547],{"class":95},[70,827,796],{"class":264},[70,829,517],{"class":95},[70,831,172],{"class":80},[70,833,834,837,839,841,843,845,847],{"class":72,"line":401},[70,835,836],{"class":543},"    callback",[70,838,547],{"class":95},[70,840,664],{"class":493},[70,842,125],{"class":80},[70,844,533],{"class":264},[70,846,517],{"class":95},[70,848,172],{"class":80},[70,850,852,855,857],{"class":72,"line":851},6,[70,853,854],{"class":80},"  }",[70,856,517],{"class":95},[70,858,172],{"class":80},[70,860,862],{"class":72,"line":861},7,[70,863,598],{"class":80},[53,865,867],{"id":866},"_3-返回多种内容","3. 返回多种内容",[211,869,870,876,882],{},[214,871,872,875],{},[26,873,874],{},"内容类型","：可以是 JavaScript 代码字符串，也可以是其他语言（如 CSS、HTML）—— Webpack 会继续用其他 Loader 处理。",[214,877,878,881],{},[26,879,880],{},"Source Map","：便于调试转换后的代码。",[214,883,884,887],{},[26,885,886],{},"元数据","：例如在 loader 中生成 AST，可以传递给下一个 loader。",[36,889,891],{"id":890},"三loader-工具库","三、Loader 工具库",[53,893,895,896],{"id":894},"_1-loader-utils","1. ",[48,897,898],{},"loader-utils",[23,900,901],{},"提供常用的辅助函数。",[61,903,905],{"className":63,"code":904,"language":65,"meta":66,"style":66},"const { getOptions, interpolateName } = require(\"loader-utils\");\n\nmodule.exports = function (source) {\n  \u002F\u002F 获取 loader 配置中的 options\n  const options = getOptions(this);\n\n  \u002F\u002F 生成文件名（带 hash 等）\n  const filename = interpolateName(this, \"[name].[hash].[ext]\", {\n    content: source,\n    context: this.rootContext,\n  });\n\n  \u002F\u002F 发出一个文件（例如生成图片）\n  this.emitFile(filename, source);\n\n  return `module.exports = ${JSON.stringify(filename)};`;\n};\n",[48,906,907,943,949,969,974,994,998,1003,1032,1045,1062,1071,1076,1082,1105,1110,1149],{"__ignoreMap":66},[70,908,909,912,915,918,920,923,926,928,931,933,935,937,939,941],{"class":72,"line":73},[70,910,911],{"class":506},"const",[70,913,914],{"class":80}," {",[70,916,917],{"class":532}," getOptions",[70,919,125],{"class":80},[70,921,922],{"class":532}," interpolateName",[70,924,925],{"class":80}," }",[70,927,503],{"class":502},[70,929,930],{"class":543}," require",[70,932,547],{"class":264},[70,934,135],{"class":107},[70,936,898],{"class":138},[70,938,135],{"class":107},[70,940,517],{"class":264},[70,942,172],{"class":80},[70,944,945],{"class":72,"line":87},[70,946,948],{"emptyLinePlaceholder":947},true,"\n",[70,950,951,953,955,957,959,961,963,965,967],{"class":72,"line":175},[70,952,77],{"class":493},[70,954,496],{"class":80},[70,956,499],{"class":493},[70,958,503],{"class":502},[70,960,507],{"class":506},[70,962,510],{"class":80},[70,964,514],{"class":513},[70,966,517],{"class":80},[70,968,84],{"class":80},[70,970,971],{"class":72,"line":355},[70,972,973],{"class":351},"  \u002F\u002F 获取 loader 配置中的 options\n",[70,975,976,978,981,983,985,987,990,992],{"class":72,"line":401},[70,977,529],{"class":506},[70,979,980],{"class":532}," options",[70,982,503],{"class":502},[70,984,917],{"class":543},[70,986,547],{"class":95},[70,988,989],{"class":493},"this",[70,991,517],{"class":95},[70,993,172],{"class":80},[70,995,996],{"class":72,"line":851},[70,997,948],{"emptyLinePlaceholder":947},[70,999,1000],{"class":72,"line":861},[70,1001,1002],{"class":351},"  \u002F\u002F 生成文件名（带 hash 等）\n",[70,1004,1006,1008,1011,1013,1015,1017,1019,1021,1023,1026,1028,1030],{"class":72,"line":1005},8,[70,1007,529],{"class":506},[70,1009,1010],{"class":532}," filename",[70,1012,503],{"class":502},[70,1014,922],{"class":543},[70,1016,547],{"class":95},[70,1018,989],{"class":493},[70,1020,125],{"class":80},[70,1022,146],{"class":107},[70,1024,1025],{"class":138},"[name].[hash].[ext]",[70,1027,135],{"class":107},[70,1029,125],{"class":80},[70,1031,84],{"class":80},[70,1033,1035,1038,1040,1042],{"class":72,"line":1034},9,[70,1036,1037],{"class":95},"    content",[70,1039,81],{"class":80},[70,1041,538],{"class":264},[70,1043,1044],{"class":80},",\n",[70,1046,1048,1051,1053,1055,1057,1060],{"class":72,"line":1047},10,[70,1049,1050],{"class":95},"    context",[70,1052,81],{"class":80},[70,1054,770],{"class":493},[70,1056,496],{"class":80},[70,1058,1059],{"class":264},"rootContext",[70,1061,1044],{"class":80},[70,1063,1065,1067,1069],{"class":72,"line":1064},11,[70,1066,854],{"class":80},[70,1068,517],{"class":95},[70,1070,172],{"class":80},[70,1072,1074],{"class":72,"line":1073},12,[70,1075,948],{"emptyLinePlaceholder":947},[70,1077,1079],{"class":72,"line":1078},13,[70,1080,1081],{"class":351},"  \u002F\u002F 发出一个文件（例如生成图片）\n",[70,1083,1085,1087,1089,1092,1094,1097,1099,1101,1103],{"class":72,"line":1084},14,[70,1086,654],{"class":493},[70,1088,496],{"class":80},[70,1090,1091],{"class":543},"emitFile",[70,1093,547],{"class":95},[70,1095,1096],{"class":264},"filename",[70,1098,125],{"class":80},[70,1100,538],{"class":264},[70,1102,517],{"class":95},[70,1104,172],{"class":80},[70,1106,1108],{"class":72,"line":1107},15,[70,1109,948],{"emptyLinePlaceholder":947},[70,1111,1113,1115,1118,1121,1124,1127,1129,1132,1135,1137,1139,1141,1144,1147],{"class":72,"line":1112},16,[70,1114,589],{"class":118},[70,1116,1117],{"class":107}," `",[70,1119,1120],{"class":138},"module.exports = ",[70,1122,1123],{"class":107},"${",[70,1125,1126],{"class":532},"JSON",[70,1128,496],{"class":107},[70,1130,1131],{"class":543},"stringify",[70,1133,547],{"class":1134},"sfo-9",[70,1136,1096],{"class":264},[70,1138,517],{"class":1134},[70,1140,166],{"class":107},[70,1142,1143],{"class":138},";",[70,1145,1146],{"class":107},"`",[70,1148,172],{"class":80},[70,1150,1152],{"class":72,"line":1151},17,[70,1153,598],{"class":80},[211,1155,1156,1179,1185,1191],{},[214,1157,1158,1161,1162,1165,1166,1165,1169,1165,1172,1165,1175,1178],{},[48,1159,1160],{},"interpolateName","：支持占位符如 ",[48,1163,1164],{},"[name]","、",[48,1167,1168],{},"[ext]",[48,1170,1171],{},"[hash]",[48,1173,1174],{},"[contenthash]",[48,1176,1177],{},"[path]"," 等。",[214,1180,1181,1184],{},[48,1182,1183],{},"getOptions","：从 loader context 中安全地提取 options。",[214,1186,1187,1190],{},[48,1188,1189],{},"parseQuery","：解析类似 URL 的 query 字符串（较少用）。",[214,1192,1193,1196],{},[48,1194,1195],{},"stringifyRequest","：将模块请求转换为相对于当前文件的相对路径。",[53,1198,192,1200],{"id":1199},"_2-schema-utils",[48,1201,1202],{},"schema-utils",[23,1204,1205],{},"校验 loader options 的 JSON Schema。",[61,1207,1209],{"className":63,"code":1208,"language":65,"meta":66,"style":66},"const { validate } = require(\"schema-utils\");\nconst schema = {\n  type: \"object\",\n  properties: {\n    test: { type: \"string\" },\n    limit: { type: \"number\" },\n  },\n};\n\nmodule.exports = function (source) {\n  const options = getOptions(this);\n  validate(schema, options, { name: \"My Loader\" });\n  \u002F\u002F ...\n};\n",[48,1210,1211,1238,1249,1265,1274,1297,1319,1324,1328,1332,1352,1370,1406,1411],{"__ignoreMap":66},[70,1212,1213,1215,1217,1220,1222,1224,1226,1228,1230,1232,1234,1236],{"class":72,"line":73},[70,1214,911],{"class":506},[70,1216,914],{"class":80},[70,1218,1219],{"class":532}," validate",[70,1221,925],{"class":80},[70,1223,503],{"class":502},[70,1225,930],{"class":543},[70,1227,547],{"class":264},[70,1229,135],{"class":107},[70,1231,1202],{"class":138},[70,1233,135],{"class":107},[70,1235,517],{"class":264},[70,1237,172],{"class":80},[70,1239,1240,1242,1245,1247],{"class":72,"line":87},[70,1241,911],{"class":506},[70,1243,1244],{"class":532}," schema",[70,1246,503],{"class":502},[70,1248,84],{"class":80},[70,1250,1251,1254,1256,1258,1261,1263],{"class":72,"line":175},[70,1252,1253],{"class":95},"  type",[70,1255,81],{"class":80},[70,1257,146],{"class":107},[70,1259,1260],{"class":138},"object",[70,1262,135],{"class":107},[70,1264,1044],{"class":80},[70,1266,1267,1270,1272],{"class":72,"line":355},[70,1268,1269],{"class":95},"  properties",[70,1271,81],{"class":80},[70,1273,84],{"class":80},[70,1275,1276,1279,1281,1283,1286,1288,1290,1293,1295],{"class":72,"line":401},[70,1277,1278],{"class":95},"    test",[70,1280,81],{"class":80},[70,1282,914],{"class":80},[70,1284,1285],{"class":95}," type",[70,1287,81],{"class":80},[70,1289,146],{"class":107},[70,1291,1292],{"class":138},"string",[70,1294,135],{"class":107},[70,1296,314],{"class":80},[70,1298,1299,1302,1304,1306,1308,1310,1312,1315,1317],{"class":72,"line":851},[70,1300,1301],{"class":95},"    limit",[70,1303,81],{"class":80},[70,1305,914],{"class":80},[70,1307,1285],{"class":95},[70,1309,81],{"class":80},[70,1311,146],{"class":107},[70,1313,1314],{"class":138},"number",[70,1316,135],{"class":107},[70,1318,314],{"class":80},[70,1320,1321],{"class":72,"line":861},[70,1322,1323],{"class":80},"  },\n",[70,1325,1326],{"class":72,"line":1005},[70,1327,598],{"class":80},[70,1329,1330],{"class":72,"line":1034},[70,1331,948],{"emptyLinePlaceholder":947},[70,1333,1334,1336,1338,1340,1342,1344,1346,1348,1350],{"class":72,"line":1047},[70,1335,77],{"class":493},[70,1337,496],{"class":80},[70,1339,499],{"class":493},[70,1341,503],{"class":502},[70,1343,507],{"class":506},[70,1345,510],{"class":80},[70,1347,514],{"class":513},[70,1349,517],{"class":80},[70,1351,84],{"class":80},[70,1353,1354,1356,1358,1360,1362,1364,1366,1368],{"class":72,"line":1064},[70,1355,529],{"class":506},[70,1357,980],{"class":532},[70,1359,503],{"class":502},[70,1361,917],{"class":543},[70,1363,547],{"class":95},[70,1365,989],{"class":493},[70,1367,517],{"class":95},[70,1369,172],{"class":80},[70,1371,1372,1375,1377,1380,1382,1384,1386,1388,1391,1393,1395,1398,1400,1402,1404],{"class":72,"line":1073},[70,1373,1374],{"class":543},"  validate",[70,1376,547],{"class":95},[70,1378,1379],{"class":264},"schema",[70,1381,125],{"class":80},[70,1383,980],{"class":264},[70,1385,125],{"class":80},[70,1387,914],{"class":80},[70,1389,1390],{"class":95}," name",[70,1392,81],{"class":80},[70,1394,146],{"class":107},[70,1396,1397],{"class":138},"My Loader",[70,1399,135],{"class":107},[70,1401,925],{"class":80},[70,1403,517],{"class":95},[70,1405,172],{"class":80},[70,1407,1408],{"class":72,"line":1078},[70,1409,1410],{"class":351},"  \u002F\u002F ...\n",[70,1412,1413],{"class":72,"line":1084},[70,1414,598],{"class":80},[36,1416,1418],{"id":1417},"四自定义-loader-典型场景","四、自定义 Loader 典型场景",[53,1420,1422],{"id":1421},"_1-语言预处理替换模板变量","1. 语言预处理（替换模板变量）",[23,1424,1425,1426,1429],{},"例如，将文件中的 ",[48,1427,1428],{},"{{VERSION}}"," 替换为构建时的版本号。",[61,1431,1433],{"className":63,"code":1432,"language":65,"meta":66,"style":66},"\u002F\u002F version-loader.js\nmodule.exports = function (source) {\n  const version = process.env.npm_package_version || \"0.0.0\";\n  return source.replace(\u002F{{VERSION}}\u002Fg, version);\n};\n",[48,1434,1435,1440,1460,1493,1521],{"__ignoreMap":66},[70,1436,1437],{"class":72,"line":73},[70,1438,1439],{"class":351},"\u002F\u002F version-loader.js\n",[70,1441,1442,1444,1446,1448,1450,1452,1454,1456,1458],{"class":72,"line":87},[70,1443,77],{"class":493},[70,1445,496],{"class":80},[70,1447,499],{"class":493},[70,1449,503],{"class":502},[70,1451,507],{"class":506},[70,1453,510],{"class":80},[70,1455,514],{"class":513},[70,1457,517],{"class":80},[70,1459,84],{"class":80},[70,1461,1462,1464,1467,1469,1471,1473,1476,1478,1481,1484,1486,1489,1491],{"class":72,"line":175},[70,1463,529],{"class":506},[70,1465,1466],{"class":532}," version",[70,1468,503],{"class":502},[70,1470,641],{"class":264},[70,1472,496],{"class":80},[70,1474,1475],{"class":264},"env",[70,1477,496],{"class":80},[70,1479,1480],{"class":264},"npm_package_version",[70,1482,1483],{"class":502}," ||",[70,1485,146],{"class":107},[70,1487,1488],{"class":138},"0.0.0",[70,1490,135],{"class":107},[70,1492,172],{"class":80},[70,1494,1495,1497,1499,1501,1503,1505,1507,1509,1511,1513,1515,1517,1519],{"class":72,"line":355},[70,1496,589],{"class":118},[70,1498,538],{"class":264},[70,1500,496],{"class":80},[70,1502,544],{"class":543},[70,1504,547],{"class":95},[70,1506,122],{"class":107},[70,1508,1428],{"class":115},[70,1510,122],{"class":107},[70,1512,575],{"class":574},[70,1514,125],{"class":80},[70,1516,1466],{"class":264},[70,1518,517],{"class":95},[70,1520,172],{"class":80},[70,1522,1523],{"class":72,"line":401},[70,1524,598],{"class":80},[53,1526,1528],{"id":1527},"_2-按需引入替换优化组件库导入","2. 按需引入替换（优化组件库导入）",[23,1530,1531,1532,1535],{},"将 ",[48,1533,1534],{},"import { Button, Input } from 'ui-library'"," 转换为具体路径，实现按需引入。",[61,1537,1539],{"className":63,"code":1538,"language":65,"meta":66,"style":66},"\u002F\u002F optimize-import-loader.js\nmodule.exports = function (source) {\n  return source.replace(\n    \u002Fimport\\s*\\{\\s*([^}]+)\\s*\\}\\s*from\\s*['\"]ui-library['\"]\u002Fg,\n    (match, names) => {\n      const imports = names\n        .split(\",\")\n        .map((name) => {\n          const trimmed = name.trim();\n          return `import ${trimmed} from 'ui-library\u002Flib\u002F${trimmed}';`;\n        })\n        .join(\"\\n\");\n      return imports;\n    },\n  );\n};\n",[48,1540,1541,1546,1566,1579,1657,1676,1689,1708,1728,1749,1782,1789,1809,1818,1823,1830],{"__ignoreMap":66},[70,1542,1543],{"class":72,"line":73},[70,1544,1545],{"class":351},"\u002F\u002F optimize-import-loader.js\n",[70,1547,1548,1550,1552,1554,1556,1558,1560,1562,1564],{"class":72,"line":87},[70,1549,77],{"class":493},[70,1551,496],{"class":80},[70,1553,499],{"class":493},[70,1555,503],{"class":502},[70,1557,507],{"class":506},[70,1559,510],{"class":80},[70,1561,514],{"class":513},[70,1563,517],{"class":80},[70,1565,84],{"class":80},[70,1567,1568,1570,1572,1574,1576],{"class":72,"line":175},[70,1569,589],{"class":118},[70,1571,538],{"class":264},[70,1573,496],{"class":80},[70,1575,544],{"class":543},[70,1577,1578],{"class":95},"(\n",[70,1580,1581,1584,1586,1589,1592,1595,1597,1599,1602,1605,1608,1610,1612,1615,1617,1619,1621,1624,1626,1628,1631,1633,1635,1637,1640,1642,1645,1647,1649,1651,1653,1655],{"class":72,"line":355},[70,1582,1583],{"class":107},"    \u002F",[70,1585,456],{"class":115},[70,1587,1588],{"class":563},"\\s",[70,1590,1591],{"class":502},"*",[70,1593,1594],{"class":111},"\\{",[70,1596,1588],{"class":563},[70,1598,1591],{"class":502},[70,1600,547],{"class":1601},"s-KJb",[70,1603,1604],{"class":493},"[",[70,1606,1607],{"class":502},"^",[70,1609,166],{"class":563},[70,1611,169],{"class":493},[70,1613,1614],{"class":502},"+",[70,1616,517],{"class":1601},[70,1618,1588],{"class":563},[70,1620,1591],{"class":502},[70,1622,1623],{"class":111},"\\}",[70,1625,1588],{"class":563},[70,1627,1591],{"class":502},[70,1629,1630],{"class":115},"from",[70,1632,1588],{"class":563},[70,1634,1591],{"class":502},[70,1636,1604],{"class":493},[70,1638,1639],{"class":563},"'\"",[70,1641,169],{"class":493},[70,1643,1644],{"class":115},"ui-library",[70,1646,1604],{"class":493},[70,1648,1639],{"class":563},[70,1650,169],{"class":493},[70,1652,122],{"class":107},[70,1654,575],{"class":574},[70,1656,1044],{"class":80},[70,1658,1659,1662,1665,1667,1670,1672,1674],{"class":72,"line":401},[70,1660,1661],{"class":80},"    (",[70,1663,1664],{"class":513},"match",[70,1666,125],{"class":80},[70,1668,1669],{"class":513}," names",[70,1671,517],{"class":80},[70,1673,805],{"class":506},[70,1675,84],{"class":80},[70,1677,1678,1681,1684,1686],{"class":72,"line":851},[70,1679,1680],{"class":506},"      const",[70,1682,1683],{"class":532}," imports",[70,1685,503],{"class":502},[70,1687,1688],{"class":264}," names\n",[70,1690,1691,1694,1697,1699,1701,1703,1705],{"class":72,"line":861},[70,1692,1693],{"class":80},"        .",[70,1695,1696],{"class":543},"split",[70,1698,547],{"class":95},[70,1700,135],{"class":107},[70,1702,125],{"class":138},[70,1704,135],{"class":107},[70,1706,1707],{"class":95},")\n",[70,1709,1710,1712,1715,1717,1719,1722,1724,1726],{"class":72,"line":1005},[70,1711,1693],{"class":80},[70,1713,1714],{"class":543},"map",[70,1716,547],{"class":95},[70,1718,547],{"class":80},[70,1720,1721],{"class":513},"name",[70,1723,517],{"class":80},[70,1725,805],{"class":506},[70,1727,84],{"class":80},[70,1729,1730,1733,1736,1738,1740,1742,1745,1747],{"class":72,"line":1034},[70,1731,1732],{"class":506},"          const",[70,1734,1735],{"class":532}," trimmed",[70,1737,503],{"class":502},[70,1739,1390],{"class":264},[70,1741,496],{"class":80},[70,1743,1744],{"class":543},"trim",[70,1746,778],{"class":95},[70,1748,172],{"class":80},[70,1750,1751,1754,1756,1759,1761,1764,1766,1769,1771,1773,1775,1778,1780],{"class":72,"line":1047},[70,1752,1753],{"class":118},"          return",[70,1755,1117],{"class":107},[70,1757,1758],{"class":138},"import ",[70,1760,1123],{"class":107},[70,1762,1763],{"class":264},"trimmed",[70,1765,166],{"class":107},[70,1767,1768],{"class":138}," from 'ui-library\u002Flib\u002F",[70,1770,1123],{"class":107},[70,1772,1763],{"class":264},[70,1774,166],{"class":107},[70,1776,1777],{"class":138},"';",[70,1779,1146],{"class":107},[70,1781,172],{"class":80},[70,1783,1784,1787],{"class":72,"line":1064},[70,1785,1786],{"class":80},"        }",[70,1788,1707],{"class":95},[70,1790,1791,1793,1796,1798,1800,1803,1805,1807],{"class":72,"line":1073},[70,1792,1693],{"class":80},[70,1794,1795],{"class":543},"join",[70,1797,547],{"class":95},[70,1799,135],{"class":107},[70,1801,1802],{"class":532},"\\n",[70,1804,135],{"class":107},[70,1806,517],{"class":95},[70,1808,172],{"class":80},[70,1810,1811,1814,1816],{"class":72,"line":1078},[70,1812,1813],{"class":118},"      return",[70,1815,1683],{"class":264},[70,1817,172],{"class":80},[70,1819,1820],{"class":72,"line":1084},[70,1821,1822],{"class":80},"    },\n",[70,1824,1825,1828],{"class":72,"line":1107},[70,1826,1827],{"class":95},"  )",[70,1829,172],{"class":80},[70,1831,1832],{"class":72,"line":1112},[70,1833,598],{"class":80},[53,1835,1837],{"id":1836},"_3-移除调试代码consolelogdebugger","3. 移除调试代码（console.log、debugger）",[61,1839,1841],{"className":63,"code":1840,"language":65,"meta":66,"style":66},"\u002F\u002F strip-debug-loader.js\nmodule.exports = function (source) {\n  const result = source.replace(\u002Fconsole\\.(log|debug|info|warn)\\(.*?\\)\\s*;?\u002Fg, \"\");\n  return result.replace(\u002Fdebugger\\s*;?\u002Fg, \"\");\n};\n",[48,1842,1843,1848,1868,1941,1978],{"__ignoreMap":66},[70,1844,1845],{"class":72,"line":73},[70,1846,1847],{"class":351},"\u002F\u002F strip-debug-loader.js\n",[70,1849,1850,1852,1854,1856,1858,1860,1862,1864,1866],{"class":72,"line":87},[70,1851,77],{"class":493},[70,1853,496],{"class":80},[70,1855,499],{"class":493},[70,1857,503],{"class":502},[70,1859,507],{"class":506},[70,1861,510],{"class":80},[70,1863,514],{"class":513},[70,1865,517],{"class":80},[70,1867,84],{"class":80},[70,1869,1870,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1897,1900,1902,1905,1907,1910,1912,1914,1916,1918,1920,1922,1924,1926,1929,1931,1933,1935,1937,1939],{"class":72,"line":175},[70,1871,529],{"class":506},[70,1873,533],{"class":532},[70,1875,503],{"class":502},[70,1877,538],{"class":264},[70,1879,496],{"class":80},[70,1881,544],{"class":543},[70,1883,547],{"class":95},[70,1885,122],{"class":107},[70,1887,552],{"class":115},[70,1889,112],{"class":111},[70,1891,547],{"class":1601},[70,1893,557],{"class":115},[70,1895,1896],{"class":502},"|",[70,1898,1899],{"class":115},"debug",[70,1901,1896],{"class":502},[70,1903,1904],{"class":115},"info",[70,1906,1896],{"class":502},[70,1908,1909],{"class":115},"warn",[70,1911,517],{"class":1601},[70,1913,560],{"class":111},[70,1915,496],{"class":563},[70,1917,566],{"class":502},[70,1919,569],{"class":111},[70,1921,1588],{"class":563},[70,1923,1591],{"class":502},[70,1925,1143],{"class":115},[70,1927,1928],{"class":502},"?",[70,1930,122],{"class":107},[70,1932,575],{"class":574},[70,1934,125],{"class":80},[70,1936,580],{"class":107},[70,1938,517],{"class":95},[70,1940,172],{"class":80},[70,1942,1943,1945,1947,1949,1951,1953,1955,1958,1960,1962,1964,1966,1968,1970,1972,1974,1976],{"class":72,"line":355},[70,1944,589],{"class":118},[70,1946,533],{"class":264},[70,1948,496],{"class":80},[70,1950,544],{"class":543},[70,1952,547],{"class":95},[70,1954,122],{"class":107},[70,1956,1957],{"class":115},"debugger",[70,1959,1588],{"class":563},[70,1961,1591],{"class":502},[70,1963,1143],{"class":115},[70,1965,1928],{"class":502},[70,1967,122],{"class":107},[70,1969,575],{"class":574},[70,1971,125],{"class":80},[70,1973,580],{"class":107},[70,1975,517],{"class":95},[70,1977,172],{"class":80},[70,1979,1980],{"class":72,"line":401},[70,1981,598],{"class":80},[23,1983,1984,1985,1987],{},"配合 ",[48,1986,221],{}," 确保在其他 loader 之前执行。",[36,1989,1991],{"id":1990},"五pitch-loader熔断机制","五、Pitch Loader（熔断机制）",[23,1993,1994,1995,1998,1999,2002,2003,2006,2007,2010],{},"每个 Loader 除了默认的 ",[48,1996,1997],{},"（默认的转换函数）"," 外，还可以导出一个 ",[48,2000,2001],{},"pitch"," 方法。pitch 在 loader 执行顺序的",[26,2004,2005],{},"第一阶段","被调用，它有机会",[26,2008,2009],{},"短路","后续的 loader。",[53,2012,2014],{"id":2013},"_1-pitch-的执行顺序","1. pitch 的执行顺序",[23,2016,2017,2018,2021],{},"对于一组 loader ",[48,2019,2020],{},"[a, b, c]","：",[2023,2024,2025,2037],"ol",{},[214,2026,2027,2028,184,2031,184,2034],{},"先调用 ",[48,2029,2030],{},"a.pitch",[48,2032,2033],{},"b.pitch",[48,2035,2036],{},"c.pitch",[214,2038,2039,2040,2042,2043,2046,2047,2050],{},"如果某个 ",[48,2041,2001],{}," 返回了非 ",[48,2044,2045],{},"undefined"," 的值，则停止执行后面的 pitch，并开始",[26,2048,2049],{},"返回","阶段：直接返回该结果给上一个 loader 的 normal 函数。",[53,2052,2054],{"id":2053},"_2-短路机制","2. 短路机制",[23,2056,2057,2058,2060],{},"如果 ",[48,2059,2033],{}," 返回了一个值，那么：",[211,2062,2063,2073,2079,2085],{},[214,2064,2065,2066,2068,2069,2072],{},"不再调用 ",[48,2067,2036],{}," 和 ",[48,2070,2071],{},"c"," 的 normal 函数。",[214,2074,2075,2078],{},[48,2076,2077],{},"b"," 的 normal 函数不会被调用（因为 pitch 已经返回）。",[214,2080,2081,2082,2084],{},"该值直接返回给 ",[48,2083,30],{}," 的 normal 函数（作为输入）。",[214,2086,2087,2088,2090],{},"然后执行 ",[48,2089,30],{}," 的 normal 函数，最后输出。",[23,2092,2093],{},"示意图：",[61,2095,2098],{"className":2096,"code":2097,"language":207},[205],"normal 执行顺序: a → b → c\npitch 执行顺序: a.pitch → b.pitch → c.pitch\n如果 b.pitch 返回内容，则跳过 c 的所有函数，并且 b 的 normal 也不执行，结果回传给 a.normal。\n",[48,2099,2097],{"__ignoreMap":66},[53,2101,2103],{"id":2102},"_3-pitch-的典型用途","3. pitch 的典型用途",[211,2105,2106,2112,2122],{},[214,2107,2108,2111],{},[26,2109,2110],{},"提前返回","：如果 loader 已经知道最终输出（例如文件是空的、不需要处理），可以直接返回。",[214,2113,2114,2117,2118,2121],{},[26,2115,2116],{},"收集信息","：在 pitch 阶段读取配置或修改请求路径（例如 ",[48,2119,2120],{},"style-loader"," 使用 pitch 将 CSS 注入到 JS 中）。",[214,2123,2124,2021,2127,1178],{},[26,2125,2126],{},"动态添加依赖",[48,2128,2129],{},"this.addDependency",[23,2131,2132],{},"示例：一个简单的 pitch loader，跳过后续处理",[61,2134,2136],{"className":63,"code":2135,"language":65,"meta":66,"style":66},"\u002F\u002F skip-loader.js\nmodule.exports = function (source) {\n  \u002F\u002F 正常情况下不会被调用（如果 pitch 返回了值）\n  return source;\n};\nmodule.exports.pitch = function (remainingRequest, precedingRequest, data) {\n  \u002F\u002F 直接返回一段代码，不再执行后面的 loader\n  return `module.exports = \"skipped\";`;\n};\n",[48,2137,2138,2143,2163,2168,2176,2180,2215,2220,2233],{"__ignoreMap":66},[70,2139,2140],{"class":72,"line":73},[70,2141,2142],{"class":351},"\u002F\u002F skip-loader.js\n",[70,2144,2145,2147,2149,2151,2153,2155,2157,2159,2161],{"class":72,"line":87},[70,2146,77],{"class":493},[70,2148,496],{"class":80},[70,2150,499],{"class":493},[70,2152,503],{"class":502},[70,2154,507],{"class":506},[70,2156,510],{"class":80},[70,2158,514],{"class":513},[70,2160,517],{"class":80},[70,2162,84],{"class":80},[70,2164,2165],{"class":72,"line":175},[70,2166,2167],{"class":351},"  \u002F\u002F 正常情况下不会被调用（如果 pitch 返回了值）\n",[70,2169,2170,2172,2174],{"class":72,"line":355},[70,2171,589],{"class":118},[70,2173,538],{"class":264},[70,2175,172],{"class":80},[70,2177,2178],{"class":72,"line":401},[70,2179,598],{"class":80},[70,2181,2182,2184,2186,2188,2190,2192,2194,2196,2198,2201,2203,2206,2208,2211,2213],{"class":72,"line":851},[70,2183,77],{"class":493},[70,2185,496],{"class":80},[70,2187,499],{"class":493},[70,2189,496],{"class":80},[70,2191,2001],{"class":543},[70,2193,503],{"class":502},[70,2195,507],{"class":506},[70,2197,510],{"class":80},[70,2199,2200],{"class":513},"remainingRequest",[70,2202,125],{"class":80},[70,2204,2205],{"class":513}," precedingRequest",[70,2207,125],{"class":80},[70,2209,2210],{"class":513}," data",[70,2212,517],{"class":80},[70,2214,84],{"class":80},[70,2216,2217],{"class":72,"line":861},[70,2218,2219],{"class":351},"  \u002F\u002F 直接返回一段代码，不再执行后面的 loader\n",[70,2221,2222,2224,2226,2229,2231],{"class":72,"line":1005},[70,2223,589],{"class":118},[70,2225,1117],{"class":107},[70,2227,2228],{"class":138},"module.exports = \"skipped\";",[70,2230,1146],{"class":107},[70,2232,172],{"class":80},[70,2234,2235],{"class":72,"line":1034},[70,2236,598],{"class":80},[53,2238,2240],{"id":2239},"_4-pitch-参数说明","4. pitch 参数说明",[211,2242,2243,2248,2254],{},[214,2244,2245,2247],{},[48,2246,2200],{},"：剩余请求字符串（从当前 loader 之后的所有 loader 加上资源路径）。",[214,2249,2250,2253],{},[48,2251,2252],{},"precedingRequest","：前面的请求字符串。",[214,2255,2256,2259],{},[48,2257,2258],{},"data","：可在 pitch 和 normal 之间共享的对象。",[2261,2262,2263],"h2",{"id":2263},"总结",[2265,2266,2267,2280],"table",{},[2268,2269,2270],"thead",{},[2271,2272,2273,2277],"tr",{},[2274,2275,2276],"th",{},"方面",[2274,2278,2279],{},"关键点",[2281,2282,2283,2304,2322,2337,2347],"tbody",{},[2271,2284,2285,2291],{},[2286,2287,2288],"td",{},[26,2289,2290],{},"执行顺序",[2286,2292,2293,2295,2296,2295,2298,2295,2300,2303],{},[48,2294,221],{}," > ",[48,2297,227],{},[48,2299,233],{},[48,2301,2302],{},"'post'","；默认从右向左执行",[2271,2305,2306,2311],{},[2286,2307,2308],{},[26,2309,2310],{},"同步\u002F异步",[2286,2312,2313,2314,2316,2317,2319,2320],{},"同步用 ",[48,2315,482],{}," 或 ",[48,2318,604],{},"；异步用 ",[48,2321,732],{},[2271,2323,2324,2329],{},[2286,2325,2326],{},[26,2327,2328],{},"工具库",[2286,2330,2331,2333,2334,2336],{},[48,2332,898],{},"（参数、命名）、",[48,2335,1202],{},"（校验）",[2271,2338,2339,2344],{},[2286,2340,2341],{},[26,2342,2343],{},"典型场景",[2286,2345,2346],{},"变量替换、按需引入移除调试代码",[2271,2348,2349,2354],{},[2286,2350,2351],{},[26,2352,2353],{},"Pitch Loader",[2286,2355,2356],{},"短路后续 loader，用于提前返回或修改请求",[23,2358,2359,2360,2362,2363,2365],{},"通过开发自定义 Loader，可以定制 Webpack 处理各种文件的方式，满足工程化中的特殊需求。高级用法常与 ",[48,2361,2001],{}," 配合，实现类似 ",[48,2364,2120],{}," 的动态注入逻辑。",[2261,2367,2368],{"id":2368},"参考文献",[23,2370,2371],{},"以下链接在编写时均可正常访问：",[2265,2373,2374,2384],{},[2268,2375,2376],{},[2271,2377,2378,2381],{},[2274,2379,2380],{},"资料",[2274,2382,2383],{},"说明",[2281,2385,2386,2398],{},[2271,2387,2388,2395],{},[2286,2389,2390],{},[30,2391,8],{"href":2392,"rel":2393},"https:\u002F\u002Fwebpack.js.org\u002Floaders\u002F",[2394],"nofollow",[2286,2396,2397],{},"官方",[2271,2399,2400,2407],{},[2286,2401,2402],{},[30,2403,2406],{"href":2404,"rel":2405},"https:\u002F\u002Fwebpack.js.org\u002Fcontribute\u002Fwriting-a-loader\u002F",[2394],"编写 Loader",[2286,2408,2409],{},"指南",[2411,2412,2413],"style",{},"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 .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 .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 .sQRbd, html code.shiki .sQRbd{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#DBEDFF}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 .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}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 .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 .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 .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s-KJb, html code.shiki .s-KJb{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":66,"searchDepth":87,"depth":87,"links":2415},[2416,2417,2418,2419,2420,2421,2422],{"id":38,"depth":175,"text":39},{"id":468,"depth":175,"text":469},{"id":890,"depth":175,"text":891},{"id":1417,"depth":175,"text":1418},{"id":1990,"depth":175,"text":1991},{"id":2263,"depth":87,"text":2263},{"id":2368,"depth":87,"text":2368},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Floader","knowledge\u002Fknowledge\u002Fbooklet\u002Fproject\u002FWebpack\u002Floader.md","md",{"items":2428},[2429,2431,2435,2439,2443,2447],{"path":32,"title":33,"description":2430,"category":10,"score":851},"Webpack 是静态模块打包器：从入口递归解析依赖，经 Loader 转换后输出一个或多个 bundle。与 Vite 对比见 Webpack 与 Vite。",{"path":2432,"title":2433,"description":2434,"category":10,"score":851},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fchunks","产物优化","Webpack 通过代码分割、Tree Shaking、压缩与资源模块等减少体积、改善缓存。原理背景见 工作原理。",{"path":2436,"title":2437,"description":2438,"category":10,"score":851},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fcompany","企业级实践","大型前端项目在 Webpack 场景下的多环境拆分、Docker 构建缓存、自定义 CLI 与微前端（Module Federation \u002F single-spa）等实践。入门见 工程化概览。",{"path":2440,"title":2441,"description":2442,"category":10,"score":851},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fadvanced","进阶配置","Webpack 进阶场景：多页面（MPA）、devServer、环境变量注入、Source Map、Module Federation 等。基础见 工作原理。",{"path":2444,"title":2445,"description":2446,"category":10,"score":851},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fwebpack\u002Fplugin","Plugin","Webpack 插件在构建生命周期钩子上扩展能力（修改资源、生成 HTML、上传 CDN 等）。背景见 工作原理；与 Loader 分工：Loader 转换单文件，插件面向整体构建。",{"path":2448,"title":2449,"description":2450,"category":10,"score":355},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fproject\u002Fother","其他配置","除 ESLint、Prettier 等规范文件外，仓库中常见的工具链与包管理配置如下。见 工程化概览。",{"series":2452,"title":12,"items":2453,"index":175,"prev":2465,"next":2466},"booklet\u002Fproject\u002Fwebpack",[2454,2456,2458,2460,2461,2463],{"path":2440,"title":2441,"date":2455,"pinned":15},"2021-10-18",{"path":2432,"title":2433,"date":2457,"pinned":15},"2025-01-28",{"path":2436,"title":2437,"date":2459,"pinned":15},"2024-07-30",{"path":7,"title":8,"date":14,"pinned":15},{"path":2444,"title":2445,"date":2462,"pinned":15},"2020-08-27",{"path":32,"title":33,"date":2464,"pinned":15},"2025-12-19",{"path":2436,"title":2437,"date":2459,"pinned":15},{"path":2444,"title":2445,"date":2462,"pinned":15}]