鎺ヤ笂鏂囷細娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 浜?- 閫掑綊鏋勫缓 module
浜斻€佺敓鎴?chunk
鐢熸垚 chunk 闃舵姒傝堪锛氬湪
compilation.finish
鍥炶皟涓墽琛岀殑 seal 鏂规硶涓紝瑙﹀彂娴烽噺閽╁瓙锛屽氨姝や镜鍏?webpack 鐨勫皝鍖呴樁娈碉紱
1.棣栧厛瀵规墍鏈?import
鍜?export
鍋氭爣璁帮紝浠ュ疄鐜版渶鍚庢瀯寤鸿祫婧愰樁娈电殑 treeshaking锛?br> 2.閬嶅巻鍏ュ彛鏂囦欢涓烘瘡涓叆鍙g敓鎴愬垵濮?chunk 鐨勫悓鏃讹紝涔熷疄渚嬪寲浜?EntryPoint(缁ф壙鑷?ChunkGroup 绫?锛屽苟寤虹珛浜嗗叆鍙?module 鍜?chunk銆乪ntryPoint 涔嬮棿鐨勮仈绯?/strong>锛?br> 3.閫氳繃 buildChunkGraph 鐨勪笁涓樁娈碉紝鐢熸垚寮傛 chunk 鍜?鍖呭惈瀹冪殑chunkGroup锛屽皢鎵€鏈?module銆乧hunk銆乧hunkGroup 閮藉缓绔嬭捣鍏宠仈锛屽舰鎴愪簡 chunkGraph銆?br> 4.鏈€鍚庡皢compilation.modules
鎺掑簭锛屽啀瑙﹀彂afterChunks 閽╁瓙
锛宑hunk 鐢熸垚缁撴潫銆?br> 杩欓儴鍒嗛兘鏄?webpack 鐨勯澶勭悊 鍜?chunks 榛樿瑙勫垯鐨勫疄鐜帮紝鍚庨潰 chunk 浼樺寲闃舵浼氭毚闇插緢澶氶挬瀛愶紝webpack 浼氭牴鎹垜浠厤缃殑鎻掍欢鏉ヨ繘琛屼紭鍖栥€?/p>
涓婁竴姝ユ垜浠?addEntry 鏂规硶 this._addModuleChain 鐨勪紶鐨勫洖璋冮噷return callback(null, module);
锛屽洖鍒?strong>compile
鏂规硶鐨?compiler.hooks.make.callAsync()
锛屾墽琛屽畠鐨勫洖璋冿細
// /lib/Compiler.js
this.hooks.make.callAsync(compilation, err => {
if (err) return callback(err);
compilation.finish(err => {
if (err) return callback(err);
compilation.seal(err => {
if (err) return callback(err);
this.hooks.afterCompile.callAsync(compilation, err => {
if (err) return callback(err);
return callback(null, compilation);
});
});
});
});
姝ゆ椂compilation.modules
宸茬粡鏈変簡鎵€鏈夌殑妯″潡锛?code>a銆乧銆乥銆乨銆?br>
鎵цcompilation.finish
鏂规硶锛岃Е鍙?strong>compilation.hooks锛歠inishModules
锛屾墽琛屾彃浠?FlagDependencyExportsPlugin 娉ㄥ唽鐨勪簨浠讹紝浣滅敤鏄亶鍘嗘墍鏈?module锛屽皢 export 鍑烘潵鐨勫彉閲忎互鏁扮粍鐨勫舰寮忥紝鍗曠嫭瀛樺偍鍒?module.buildMeta.providedExports 鍙橀噺涓嬨€?br>
鐒跺悗閫氳繃閬嶅巻涓烘瘡涓€涓?module 鎵цcompilation.reportDependencyErrorsAndWarnings
锛屾敹闆嗙敓鎴愬畠浠椂鏆撮湶鍑烘潵鐨?err 鍜?warning銆?/p>
鏈€鍚庤蛋鍥炶皟鎵цcompilation.seal
锛屾彁渚涗簡娴烽噺璁╂垜浠镜鍏?webpack 鏋勫缓娴佺▼鐨?hooks銆?strong>seal 瀛楅潰鎰忔€濇槸灏佸寘锛屼篃灏辨槸寮€濮嬪涓婁竴姝ョ敓鎴愮殑 module 缁撴灉杩涜灏佽銆?/strong>
鍏堟墽琛?(鎴戜滑鍏堢暐杩囨病鏈夋敞鍐屾柟娉曠殑閽╁瓙)this.hooks.seal.call();
锛岃Е鍙戞彃浠?WarnCaseSensitiveModulesPlugin锛氬湪 compilation.warnings 娣诲姞 妯″潡鏂囦欢璺緞闇€瑕佸尯鍒嗗ぇ灏忓啓鐨勮鍛娿€?/p>
鍐嶆槸this.hooks.optimizeDependencies.call(this.modules)
锛?strong>production 妯″紡浼氳Е鍙戞彃浠讹細
SideEffectsFlagPlugin
锛氳瘑鍒?package.json 鎴栬€?module.rules 鐨?sideEffects 鏍囪鐨勭函 ES2015 妯″潡锛堢函鍑芥暟)锛屽畨鍏ㄥ湴鍒犻櫎鏈敤鍒扮殑 export 瀵煎嚭锛?/li>FlagDependencyUsagePlugin
锛氱紪璇戞椂鏍囪渚濊禆unused harmony export
锛岀敤浜?Tree shaking
5.1 chunk 鍒濆鍖?/h4>
鍦ㄨЕ鍙?strong>compilation.hooks锛歜eforeChunks
鍚庯紝寮€濮嬮亶鍘嗗叆鍙e璞?this._preparedEntrypoints锛屾瘡涓叆鍙?module 閮戒細閫氳繃addChunk
鍘诲垱寤轰竴涓┖ chunk(骞舵坊鍔犲埌compilation.chunks
)锛?strong>姝ゆ椂涓嶅寘鍚换浣曚笌涔嬬浉鍏宠仈鐨?module銆備箣鍚庡疄渚嬪寲涓€涓?EntryPoint锛屾妸瀹冩坊鍔犲埌compilation.chunkGroups
涓€傛帴涓嬫潵璋冪敤 GraphHelpers 妯″潡鎻愪緵鐨勬柟娉曟潵寤虹珛璧?chunkGroup 鍜?chunk 涔嬮棿鐨勮仈绯伙紝浠ュ強 chunk 鍜?鍏ュ彛 module 涔嬮棿鐨勮仈绯?杩欓噷杩樻湭娑夊強鍒板叆鍙d緷璧栫殑 module)锛?/p>
// /lib/Compilation.js
for (const preparedEntrypoint of this._preparedEntrypoints) {
const module = preparedEntrypoint.module;
const name = preparedEntrypoint.name;
// addChunk 鏂规硶杩涜缂撳瓨鍒ゆ柇鍚庢墽琛?new Chunk(name)锛屽苟鍚屾椂娣诲姞 chunk 鍒?compilation.chunks
const chunk = this.addChunk(name);
// Entrypoint 绫绘墿灞曚簬 ChunkGroup 绫伙紝鏄?chunks 鐨勯泦鍚堬紝涓昏鐢ㄦ潵浼樺寲 chunk graph
const entrypoint = new Entrypoint(name); // 姣忎竴涓?entryPoint 灏辨槸涓€涓?chunkGroup
entrypoint.setRuntimeChunk(chunk); // 璁剧疆 runtimeChunk锛屽氨鏄繍琛屾椂 chunk
entrypoint.addOrigin(null, name, preparedEntrypoint.request);
this.namedChunkGroups.set(name, entrypoint);
this.entrypoints.set(name, entrypoint);
this.chunkGroups.push(entrypoint); // 鎶?entryPoint 娣诲姞鍒?chunkGroups
// 寤虹珛 chunkGroup 鍜?chunk 涔嬮棿鐨勮仈绯伙細
GraphHelpers.connectChunkGroupAndChunk(entrypoint, chunk);
// 寤虹珛 chunk 鍜?鍏ュ彛 module 涔嬮棿鐨勮仈绯?杩欓噷杩樻湭娑夊強鍒板叆鍙g殑渚濊禆妯″潡)
GraphHelpers.connectChunkAndModule(chunk, module);
chunk.entryModule = module;
chunk.name = name;
// 鏍规嵁鍚勪釜妯″潡渚濊禆鐨勬繁搴︼紙澶氭渚濊禆鍙栨渶灏忓€硷級璁剧疆 module.depth锛屽叆鍙fā鍧楀垯涓?depth = 0銆?
this.assignDepth(module);
}
姣斿鎴戜滑鐨?demo锛屽彧閰嶇疆浜嗕竴涓叆鍙o紝閭d箞杩欐椂浼氱敓鎴愪竴涓?chunkGroup(Entrypoint) 鍜屼竴涓?chunk锛岃繖涓?chunk 鐩墠鍙寘鍚叆鍙?module銆?/p>
5.2 鐢熸垚 chunk graph
鎵ц buildChunkGraph(this, /** @type {Entrypoint[]} */ (this.chunkGroups.slice()));
buildChunkGraph
鏂规硶鐢ㄤ簬鐢熸垚骞朵紭鍖?chunk 渚濊禆鍥撅紝寤虹珛璧?module銆乧hunk銆乧hunkGroup 涔嬮棿鐨勫叧绯汇€傚垎涓轰笁闃舵锛?/p>
// /lib/buildChunkGraph.js
// PART ONE
visitModules(compilation, inputChunkGroups, chunkGroupInfoMap, chunkDependencies, blocksWithNestedBlocks, allCreatedChunkGroups);
// PART TWO
connectChunkGroups(blocksWithNestedBlocks, chunkDependencies, chunkGroupInfoMap);
// Cleaup work
cleanupUnconnectedGroups(compilation, allCreatedChunkGroups);
绗竴闃舵 visitModules
鍏堟墽琛岋細visitModules 鐨?const blockInfoMap = extraceBlockInfoMap(compilation);
瀵规湰娆?compliation.modules 杩涜涓€娆¤凯浠i亶鍘嗭紝鎰忓湪瀹屽畬鏁存暣鏀堕泦鎵€鏈夌殑妯″潡(鍚屾銆佸紓姝?鍙婃瘡涓ā鍧楃殑鐩存帴渚濊禆銆?/p>
鍏蜂綋澶勭悊閫昏緫锛?br>
閬嶅巻姣忎釜妯″潡compilation.modules
锛屽厛鎶婂叾鍚屾渚濊禆(dependencies
)瀛樺叆 modules Set 闆嗭紝鍐嶉亶鍘嗗紓姝ヤ緷璧?blocks
)锛屾妸姣忎釜寮傛渚濊禆瀛樺叆妯″潡鐨?blocks 鏁扮粍銆?br>
鐒跺悗杩欎簺寮傛渚濊禆浼氬啀鍔犲叆鍒?code>while寰幆閬嶅巻涓?浣滀负涓€涓ā鍧?锛屼笉浠呬负瀹冨湪blockInfoMap
鍗曠嫭寤虹珛璧蜂竴涓?code>ImportDependenciesBlock绫诲瀷鐨勬暟鎹?閲岄潰鍖呭惈杩欎釜寮傛 module 鏈韩)锛屽啀鍘婚亶鍘嗗畠瀛樺偍涓€涓?code>NormalModule绫诲瀷鐨勬暟鎹?鍖呭惈瀹冪殑鍚屾 modules 鍜屽紓姝?blocks)锛屼箣鍚庨亣鍒板紓姝ヤ緷璧栭兘鏄紭鍏堣繖鏍峰鐞嗗紓姝ヤ緷璧栥€?/p>
閬嶅巻缁撴潫馃敋鍚庝細寤虹珛璧峰熀鏈殑 Module Graph锛屽寘鎷墍鏈夌殑
NormalModule
鍜?code>ImportDependenciesBlock锛屽瓨鍌ㄥ湪涓€涓?strong>blockInfoMap
Map 琛ㄥ綋涓?姣忎竴椤圭殑鍊奸兘鏄畠浠殑鐩存帴渚濊禆锛屽悓姝ュ瓨 modules锛屽紓姝ュ瓨 blocks)銆?br> 浠ャ€愭祬鏋?webpack 鎵撳寘娴佺▼(鍘熺悊) - 妗堜緥 demo銆戜负渚嬶紝寰楀埌 blockInfoMap锛?/p>
鐪嬪叿浣撴暟鎹簲璇ヨ兘澶ц嚧鐞嗚В纰板埌寮傛灏卞幓杩唬閬嶅巻寮傛鐨勫鐞嗛『搴忥細
// blockInfoMap
{
0: {
key: NormalModule, // a锛宒ebugId锛?000锛宒epth锛?
value: {
blocks: [ImportDependenciesBlock], // 寮傛 c
modules: [NormalModule] // b (modules涓簊et缁撴瀯) debugId锛?002锛宒epth锛?
}
},
1: {
key: ImportDependenciesBlock,
value: {
blocks: [],
modules: [NormalModule] // c锛宒ebugId锛?001锛宒epth锛?
}
},
2: {
key: NormalModule, // c锛宒ebugId锛?001锛宒epth锛?
value: {
blocks: [ImportDependenciesBlock], // 寮傛 b
modules: [NormalModule] // d锛宒ebugId锛?004锛宒epth锛?
}
}
3: {
key: ImportDependenciesBlock,
value: {
blocks: [],
modules: [NormalModule] // b锛宒ebugId锛?002锛宒epth锛?
}
},
4: {
key: NormalModule, // b锛宒ebugId锛?002锛宒epth锛?
value: {
blocks: [],
modules: [NormalModule] // d锛宒ebugId锛?004锛宒epth锛?
}
},
5: {
key: NormalModule, // d锛宒ebugId锛?004锛宒epth锛?
value: {
blocks: [],
modules: []
}
}
}
瀛樺偍瀹屽叆鍙fā鍧?a 鐨勭洿鎺ヤ緷璧?鍚屾鍜屽紓姝?锛屼細浼樺厛鍏堝幓寰幆澶勭悊瀹冪殑寮傛渚濊禆 c锛屾敹闆?c 鐨勭洿鎺ヤ緷璧?鍚屾鍜屽紓姝?锛岀劧鍚庡張浼樺厛閬嶅巻 c 鐨勫紓姝ヤ緷璧?..杩囩▼涓亣鍒扮殑鎵€鏈夊紓姝ヤ緷璧栭兘浼氬缓绔嬩竴涓?code>ImportDependenciesBlock瀵硅薄锛屽€煎唴鍖呭惈涓€椤瑰唴瀹逛负瀹冭嚜韬殑NormalModule
銆傚悓鏃跺亣濡傛湁閲嶅鐨勫紓姝ユā鍧楋紝浼氱敓鎴愬椤?code>ImportDependenciesBlock銆傚叾浣欎細鐢熸垚鍑犻」鍜?compliation.modules 涓€涓€瀵瑰簲鐨?code>NormalModule(a銆乥銆乧銆乨)
鎺ョ潃鐢?code>reduceChunkGroupToQueueItem鍑芥暟澶勭悊鐩墠鍙湁涓€涓?EntryPoint 鐨?chunkGroups锛?/p>
// 鐢?reduceChunkGroupToQueueItem 澶勭悊姣忎竴涓?chunkGroup
let queue = inputChunkGroups
.reduce(reduceChunkGroupToQueueItem, [])
.reverse();
灏嗗畠杞寲涓轰竴涓?queue 鏁扮粍锛屾瘡椤逛负鍏ュ彛 module銆乧hunk 浠ュ強瀵瑰簲鐨?action 绛変俊鎭粍鎴愮殑瀵硅薄锛?strong>璇﹁涓嬮潰婧愮爜銆?br>
璇存槑涓?strong>action
锛氭ā鍧楅渶瑕佽澶勭悊鐨勯樁娈电被鍨嬶紝涓嶅悓绫诲瀷鐨勬ā鍧椾細缁忚繃涓嶅悓鐨勬祦绋嬪鐞嗭紝鍒濆涓?ENTER_MODULE: 1锛屽叏閮ㄧ被鍨嬪涓嬶細
ADD_AND_ENTER_MODULE = 0
ENTER_MODULE = 1
PROCESS_BLOCK = 2
LEAVE_MODULE = 3
绱ц窡鐫€璁剧疆chunkGroupInfoMap
锛屽畠鏄犲皠浜嗘瘡涓?chunkGroup 鍜屼笌瀹冪浉鍏崇殑淇℃伅瀵硅薄銆?/p>
// /lib/buildChunkGraph.js
for (const chunk of chunkGroup.chunks) {
const module = chunk.entryModule;
queue.push({
action: ENTER_MODULE, // 闇€瑕佽澶勭悊鐨勬ā鍧楃被鍨嬶紝涓嶅悓澶勭悊绫诲瀷鐨勬ā鍧椾細缁忚繃涓嶅悓鐨勬祦绋嬪鐞嗭紝鍒濆涓?ENTER_MODULE: 1
block: module, // 鍏ュ彛 module
module, // 鍏ュ彛 module
chunk, // seal 闃舵涓€寮€濮嬩负姣忎釜鍏ュ彛 module 鍒涘缓鐨?chunk锛屽彧鍖呭惈鍏ュ彛 module
chunkGroup // entryPoint
});
}
chunkGroupInfoMap.set(chunkGroup, {
chunkGroup,
minAvailableModules: new Set(), // chunkGroup 鍙拷韪殑鏈€灏?module 鏁版嵁闆?
minAvailableModulesOwned: true,
availableModulesToBeMerged: [], // 閬嶅巻鐜妭鎵€浣跨敤鐨?module 闆嗗悎
skippedItems: [],
resultingAvailableModules: undefined,
children: undefined
});
鐒跺悗鍩轰簬module graph
锛屽 queue 杩涜浜?2 灞傞亶鍘嗐€傛垜浠彁渚涚殑 demo 鏄崟鍏ュ彛锛屽洜姝?queue 鍙湁涓€椤规暟鎹€?/p>
// /lib/buildChunkGraph.js
// 鍩轰簬 Module graph 鐨勮凯浠i亶鍘嗭紝涓嶇敤閫掑綊鍐欐槸涓轰簡闃叉鍙兘鐨勫爢鏍堟孩鍑?
while (queue.length) { // 澶栧眰閬嶅巻
logger.time("visiting");
while (queue.length) { // 鍐呭眰閬嶅巻
const queueItem = queue.pop(); // 鍒犻櫎骞惰繑鍥?queue 鏁扮粍鐨勬渶鍚庝竴椤?
// ...
if (chunkGroup !== queueItem.chunkGroup) {
// 閲嶇疆鏇存柊 chunkGroup
}
switch (queueItem.action) {
case ADD_AND_ENTER_MODULE: {
// 濡傛灉 queueItem.module 鍦?minAvailableModules锛屽垯灏嗚 queueItem 瀛樺叆 skippedItems
if (minAvailableModules.has(module)) {
Items.push(queueItem);
break;
}
// 寤虹珛 chunk 鍜?module 涔嬮棿鐨勮仈绯伙紝灏嗕緷璧栫殑 module 瀛樺叆璇?chunk 鐨?_modules 灞炴€ч噷锛屽皢 chunk 瀛樺叆 module 鐨?_chunks 閲?
// 濡傛灉 module 宸茬粡鍦?chunk 涓垯缁撴潫 switch
if (chunk.addModule(module)) {
module.addChunk(chunk);
}
}
case ENTER_MODULE: {
// 璁剧疆 chunkGroup._moduleIndices 鍜?module.index锛岀劧鍚?
// ...
// 缁?queue push 涓€椤?queueItem(action 涓?LEAVE_MODULE)锛屼緵鍚庨潰閬嶅巻鐨勬祦绋嬩腑浣跨敤銆?
queue.push({
action: LEAVE_MODULE,
block,
module,
chunk,
chunkGroup
});
}
case PROCESS_BLOCK: {
// 1. 浠?blockInfoMap 涓煡璇㈠埌褰撳墠 queueItem 鐨勬ā鍧楁暟鎹?
const blockInfo = blockInfoMap.get(block);
// 2. 閬嶅巻褰撳墠妯″潡鐨勫悓姝ヤ緷璧?娌℃湁鍒欏瓨鍏?queue锛屽叾涓?queueItem.action 閮借涓?ADD_AND_ENTER_MODULE
for (const refModule of blockInfo.modules) {
if (chunk.containsModule(refModule)) {
// 璺宠繃宸茬粡瀛樺湪浜?chunk 鐨勫悓姝ヤ緷璧?
continue;
}
// 濡傛灉宸茬粡瀛樺湪浜庣埗 chunk (chunkGroup 鍙拷韪殑鏈€灏?module 鏁版嵁闆?-- minAvailableModules)
// 鍒欏皢璇?queueItem push 鍒?skipBuffer(action 涓?ADD_AND_ENTER_MODULE)锛屽苟璺宠繃璇ヤ緷璧栫殑閬嶅巻
// 鍊掑簭灏?skipBuffer 娣诲姞 skippedItems锛宷ueueBuffer 娣诲姞鍒?queue
// enqueue the add and enter to enter in the correct order
// this is relevant with circular dependencies
// 浠ヤ笂閮戒笉绗﹀悎鍒欏皢 queueItem push 鍒?queueBuffer(action 涓?ADD_AND_ENTER_MODULE)
queueBuffer.push({
action: ADD_AND_ENTER_MODULE,
block: refModule,
module: refModule,
chunk,
chunkGroup
});
}
// 3. 鐢?iteratorBlock 鏂规硶杩唬閬嶅巻妯″潡鎵€鏈夊紓姝ヤ緷璧?blocks
for (const block of blockInfo.blocks) iteratorBlock(block);
if (blockInfo.blocks.length > 0 && module !== block) {
blocksWithNestedBlocks.add(block);
}
}
case LEAVE_MODULE: {
// 璁剧疆 chunkGroup._moduleIndices2 鍜?module.index2
}
}
}
// 涓婃枃 while (queue.length) 浠庡叆鍙?module 寮€濮嬶紝寰幆灏嗘墍鏈夊悓姝ヤ緷璧栭兘鍔犲叆鍒板悓涓€涓?chunk 閲岋紝灏嗗叆鍙?module 鍙婂畠鐨勫悓姝ヤ緷璧栭噷鐨勫紓姝ヤ緷璧栭兘鍚勮嚜鏂板缓浜哻hunkGroup 鍜?chunk锛屽苟灏嗗紓姝ユā鍧楀瓨鍏?queueDelayed锛屽紓姝ヤ緷璧栦腑鐨勫紓姝ヤ緷璧栬繕鏈鐞嗐€?
while (queueConnect.size > 0) {
// 璁$畻鍙敤妯″潡
// 1. 鍦?chunkGroupInfoMap 涓缃墠涓€涓?chunkGroup 鐨?info 瀵硅薄鐨?resultingAvailableModules銆乧hildren
// 2. 鍦?chunkGroupInfoMap 涓垵濮嬪寲鏂扮殑 chunkGroup 涓庝粬鐩稿叧鐨?info 瀵硅薄鐨勬槧灏勫苟璁剧疆浜?availableModulesToBeMerged
if (outdatedChunkGroupInfo.size > 0) {
// 鍚堝苟鍙敤妯″潡
// 1. 鑾峰彇/璁剧疆鏂扮殑 chunkGroup info 瀵硅薄鐨?minAvailableModules
// 2. 灏嗘柊鐨?chunkGroup info 瀵硅薄鐨?skippedItems push 鍒?queue
// 3. 濡傛灉鏂扮殑 chunkGroup info 瀵硅薄鐨?children 涓嶄负绌猴紝鍒欐洿鏂?queueConnect 閫掑綊寰幆
}
}
// 褰?queue 闃熷垪鐨勬墍鏈夐」閮借澶勭悊鍚庯紝鎵ц queueDelayed
// 鎶?queueDelayed 鏀惧叆 queue 璧?while 鐨勫灞傚惊鐜紝鐩殑鏄湪鎵€鏈夊悓姝ヤ緷璧?while 澶勭悊瀹屼箣鍚庯紝鎵嶅鐞嗗紓姝ユā鍧?
// 濡傛灉寮傛妯″潡閲岃繕鏈夊紓姝ヤ緷璧栵紝灏嗘斁鍒颁竴涓嬫鐨?queueDelayed 璧?while 鐨勫灞傚惊鐜?
if (queue.length === 0) {
const tempQueue = queue; // ImportDependenciesBlock
queue = queueDelayed.reverse();
queueDelayed = tempQueue;
}
}
while 寰幆鍙鏉′欢涓?true 灏变細涓€鐩村惊鐜唬鐮佸潡锛屽彧鏈夊綋鏉′欢涓嶆垚绔嬫垨鑰呭唴閮ㄦ湁if(condition){ return x;}
銆?code>if(condition){ break; }鎵嶈兘璺冲嚭寰幆銆? while+push 闃查€掑綊鐖嗘爤锛屽悗搴忔繁搴︿紭鍏?
杩涘叆鍐呭眰閬嶅巻锛屽尮閰嶅埌case ENTER_MODULE
锛屼細缁?queue push 涓€涓?action 涓?code>LEAVE_MODULE鐨?queueItem 椤逛緵鍚庨潰閬嶅巻娴佺▼涓娇鐢ㄣ€傜劧鍚庤繘鍏ュ埌PROCESS_BLOCK
闃舵锛?/p>
浠?code>blockInfoMap涓煡璇㈠埌褰撳墠 queueItem 鐨勬ā鍧楁暟鎹紝鍙湁褰撳墠妯″潡鐨勭洿鎺ヤ緷璧?/strong>锛屽湪鏈緥灏辨槸锛?/p>
鎺ヤ笅鏉ラ亶鍘嗘ā鍧楃殑鎵€鏈夊崟灞傚悓姝ヤ緷璧?modules锛岃烦杩囧凡缁忓瓨鍦ㄤ簬 chunk 鐨勫悓姝ヤ緷璧栵紱濡傛灉鍚屾渚濊禆宸插湪 minAvailableModules(chunkGroup 鍙拷韪殑鏈€灏?module 鏁版嵁闆?锛屽垯灏?queueItem push 鍒?skipBuffer锛岀劧鍚庤烦鍑鸿渚濊禆鐨勯亶鍘嗭紱浠ヤ笂閮芥病鏈夊垯灏?queueItem 瀛樺叆缂撳啿鍖?queueBuffer锛宎ction 閮借涓? 鎺ヤ笅鏉ヨ皟鐢?strong> 馃挭灏藉姏璇村緱閫氫織浜涚殑鎬荤粨锛?br>
灏嗘ā鍧?strong>鐩存帴鍚屾渚濊禆 鐒跺悗璧?code>while (queueConnect.size > 0)寰幆锛屾洿鏂颁簡 鐒跺悗绛夊唴灞傚惊鐜妸 queue 鏁扮粍 (鍐呭眰鍙妯″潡鎵€鏈夊悓姝ヤ緷璧?/strong>) 涓€涓釜鍙嶅簭澶勭悊瀹?鏁伴噺涓?)锛屽氨鎶?queueDelayed 璧嬬粰 queue 锛岃蛋澶栭儴 children 涓烘瘡椤圭殑瀛?chunkGroup锛?strong>resultingAvailableModules 姝ゆ椂鐨?code>compilation.chunkGroups鏈変笁涓?chunkGroup锛?br>
鍖呭惈涓€涓?code>_modules: { a, b, d } chunk 鐨?EntryPoint锛涘寘鍚竴涓?code>_modules: { c } chunk 鐨?chunkGroup(鍏ュ彛寮傛寮曞叆鐨?c 鍒涘缓)锛涘寘鍚竴涓┖ chunk 鐨?chunkGroup(c 寮曞叆 b 鏃跺垱寤?銆?br>
鍗冲叆鍙e拰瀹冩墍鏈夊悓姝ヤ緷璧栫粍鎴愪竴涓?chunk(鍖呭惈鍦?EntryPoint 鍐?锛屾瘡涓紓姝ヤ緷璧栨垚涓轰竴涓?chunk(鍚勮嚜鍦ㄤ竴涓?chunkGroup 鍐?銆傞亣鍒扮浉鍚岀殑寮傛妯″潡浼氶噸澶嶅垱寤?chunk 鍜?chunkGroup锛屽鐞?chunk 鍚屾妯″潡鏃堕亣鍒板凡瀛樺湪浜庡叆鍙?chunk 鐨勬ā鍧楀皢璺宠繃锛屼笉鍐嶅瓨鍏?code>chunk._modules銆?/p>
閬嶅巻 chunkDependencies锛屾牴鎹?ImportDependenciesBlock(block) 寤虹珛浜嗕笉鍚?chunkGroup 涔嬮棿鐨勭埗瀛愬叧绯汇€?br>
鏂囧瓧寰堢粫锛屽叧浜?chunkDependencies 鐢ㄤ竴涓ā鍧楁洿澶氱殑鍥惧氨瀹规槗鐞嗚В寰楀浜嗭細 杩欎釜渚嬪瓙鐨?chunkDependencies 鏄繖鏍风殑锛?/p>
閬嶅巻鏃?strong>瀛?chunkgroup 鐨?code>chunks[]._modules濡傛灉鏈夌埗 chunkGroup 鐨勫彲鐢ㄦā鍧?code>resultingAvailableModules涓笉鍖呭惈鐨勬柊妯″潡ADD_AND_ENTER_MODULE
(鍗充笅娆¢亶鍘嗚繖涓?queueItem 鏃讹紝浼氬厛杩涘叆鍒?ADD_AND_ENTER_MODULE)銆傚悓姝?modules 閬嶅巻瀹岋紝灏嗗緱鍒扮殑 queueBuffer 鍙嶅簭娣诲姞鍒?queue銆備篃灏辨槸鍚庨潰鐨勫唴灞傞亶鍘嗕腑锛屼細浼樺厛澶勭悊鍚屾渚濊禆宓屽鐨勫悓姝ユā鍧楋紝(涓嶉噸澶嶅湴)娣诲姞瀹屽啀鍘诲鐞嗗悓绾у悓姝ヤ緷璧?/strong>銆?/p>
iteratorBlock
addChunkInGroup
涓鸿繖涓紓姝?block 鍒涘缓涓€涓?chunk 鍜?chunkGroup锛屽悓鏃跺缓绔嬭繖涓よ€呬箣闂寸殑鑱旂郴銆傛鏃惰繖涓?chunk 鏄┖鐨勶紝杩樻病鏈夋坊鍔犱换浣曞畠鐨勪緷璧栵紱chunkDependencies
Map 琛ㄤ腑 鉃★笍 褰撳墠 module 鎵€灞?chunkGroup (Map 鐨?key)涓嬶紝姣忎竴閮芥槸{ block: ImportDependenciesBlock, chunkGroup: chunkGroup }
鐨勫舰寮忋€傚缓绔嬭捣 block 鍜屽畠鎵€灞?chunkGroup 鍜?鐖?chunkGroup 涔嬮棿鐨勪緷璧栧叧绯汇€俢hunkDependencies 琛ㄤ富瑕佺敤浜庡悗闈紭鍖?chunk graph锛?/li>
PROCESS_BLOCK
, module: 褰撳墠 block 鎵€灞?module, block: 褰撳墠寮傛 block, chunk: 鏂?chunkGroup 涓殑绗竴涓?chunk, chunkGroup: 鏂?chunkGroup } 锛岃椤逛富瑕佺敤浜?queue 鐨勫灞傞亶鍘嗐€?/li>
iteratorBlock
澶勭悊瀹屽綋鍓嶆ā鍧楁墍鏈夌洿鎺ュ紓姝ヤ緷璧?(block) 鍚庯紝缁撴潫鏈疆鍐呭眰閬嶅巻銆?br>
鍓嶉潰涓?queue push 浜嗕袱椤?queueItem锛屼竴涓槸鍏ュ彛妯″潡 a(action 涓?LEAVE_MODULE
)锛屼竴涓槸鍚屾妯″潡 b(action 涓?ADD_AND_ENTER_MODULE
)銆傚洜姝ょ户缁亶鍘?queue 鏁扮粍锛屽弽搴忓厛閬嶅巻 b锛屽尮閰嶅埌ADD_AND_ENTER_MODULE
锛屾妸 b 娣诲姞鍒?鍏ュ彛 chunk (_modules
灞炴€?涓紝涔熸妸鍏ュ彛 chunk 瀛樺叆 b 妯″潡鐨?code>_chunks灞炴€ч噷銆傜劧鍚庤繘鍏?code>ENTRY_MODULE闃舵锛屾爣璁颁负LEAVE_MODULE
锛屾坊鍔犲埌 queue銆?br>
鐒跺悗杩涘叆PROCESS_BLOCK
澶勭悊 b 鐨勫悓姝ヤ緷璧栧拰寮傛渚濊禆(杩囩▼濡備笂鏂?锛?/p>
鏍囪涓?code>ADD_AND_ENTER_MODULE娣诲姞鍒?queue 鐢ㄤ簬鎺ヤ笅鏉ョ殑閬嶅巻锛宲ush 鏃跺叾浣欏睘鎬?block 鍜?module 鏄畠鏈韩锛?chunk銆乧hunkGroup 涓嶅彉锛?br>
鐩存帴寮傛渚濊禆鍒欐爣璁颁负PROCESS_BLOCK
娣诲姞鍒扮敤浜庡灞傞亶鍘嗙殑 queueDelayed锛宲ush 鏃朵紶鐨勬槸鏂扮殑 chunk 鍜?chunkGroup锛宐lock 鏄畠鏈韩锛宮odule 鏄畠鐨勭埗妯″潡銆傚悓鏃朵細涓烘寮傛渚濊禆鏂板缓涓€涓寘鍚竴涓┖ chunk 鐨?chunkGroup銆?br>
澶栧眰 while 鐨勬墽琛屾椂鏈烘槸绛夋墍鏈夊叆鍙fā鍧楃殑鍚屾渚濊禆(鍖呮嫭闂存帴)閮藉鐞嗗畬鍚庛€?br>
寤虹珛鍒濇鐨?chunk graph 椤哄簭鍙互绠€鍗曞湴鎹嬫垚锛?br>
1.棣栧厛鍏ュ彛鍜屾墍鏈?鐩存帴/闂存帴)鍚屾渚濊禆褰㈡垚涓€涓?chunkGroup 缁?娣诲姞妯″潡鐨勯『搴忎负锛氬厛鏄悓姝ヤ緷璧栧祵濂楃殑鍚屾渚濊禆閮藉鐞嗗畬锛屽啀鍘婚亶鍘嗗钩绾х殑鍚屾渚濊禆)锛?br>
2.鐒跺悗鎸夋瘡涓紓姝ヤ緷璧栫殑鐖舵ā鍧楄澶勭悊鐨勯『搴?/strong>锛屼负瀹冧滑鍚勮嚜寤虹珛涓€涓?chunk 鍜?chunkGroup銆傚紓姝?chunk 涓彧浼氬寘鍚叆鍙?chunk 涓笉瀛樺湪鐨勫悓姝ヤ緷璧栥€傜浉鍚岀殑寮傛妯″潡浼氶噸澶嶅垱寤?chunk銆?/p>
chunkGroupInfoMap
涓埗 chunkGroup 鐨?info 瀵硅薄锛屽垵濮嬪寲鏂扮殑 chunkGroup info 瀵硅薄锛屽苟鑾峰彇浜嗘渶灏忓彲鐢ㄦā鍧椼€?/p>
while(queue.length)
寰幆澶勭悊寮傛渚濊禆 (鐪熸澶勭悊寮傛妯″潡)銆傝繖鏃惰繖浜?queueItem 鐨?action 閮戒负PROCESS_BLOCK
锛宐lock 閮戒负 ImportDependenciesBlock 渚濊禆銆傛洿鏂?chunkGroup 鍚庯紝 switch 鐩存帴璧?PROCESS_BLOCK 鑾峰緱寮傛椤瑰搴旂殑鐪熸妯″潡锛屽拰涔嬪墠鍚屾妯″潡涓€鏍峰鐞?鏈夊紓姝ヤ緷璧栧氨鏂板缓 chunk 鍜?chunkGroup [鏃犺涔嬪墠鏃犱负鍚屾牱鐨勫紓姝ュ潡鍒涘缓杩?chunkGroup锛屽潎浼氶噸澶嶅垱寤篯锛屽苟鏀惧叆 queueDelayed)锛屽鐞嗘暟鎹兘灏嗗瓨鍌ㄥ湪鏂扮殑 chunkGroup 瀵硅薄涓娿€傛渶缁堝緱鍒颁竴涓?Map 缁撴瀯鐨?code>chunkGroupInfoMap銆備互 demo 涓轰緥锛?/p>
// chunkGroupInfoMap Map 瀵硅薄
[
0: {
key: Entrypoint, // groupDebugId: 5000
value: {
availableModulesToBeMerged: Array(0) // 閬嶅巻鐜妭鎵€浣跨敤鐨?module 闆嗗悎
children: Set(1) {} // 瀛?chunkGroup锛実roupDebugId: 5001
chunkGroup: Entrypoint
minAvailableModules: Set(0) // chunkGroup 鍙拷韪殑鏈€灏?module 鏁版嵁闆?
minAvailableModulesOwned: true
resultingAvailableModules: Set(3) // 杩欎釜 chunkGroup 鐨勫彲鐢ㄦā鍧?a b d
skippedItems: Array(0)
}
},
1: {
key: ChunkGroup, // groupDebugId: 5001
value: {
availableModulesToBeMerged: Array(0)
children: Set(1) {} // 瀛?chunkGroup锛実roupDebugId: 5002
chunkGroup: Entrypoint
minAvailableModules: Set(3) // a b d
minAvailableModulesOwned: true
resultingAvailableModules: Set(4) // 杩欎釜 chunkGroup 鐨勫彲鐢ㄦā鍧?a b d c
skippedItems: Array(1) // d
}
}
2: {
key: ChunkGroup, // groupDebugId: 5002
value: {
availableModulesToBeMerged: Array(0)
children: undefined
chunkGroup: Entrypoint
minAvailableModules: Set(4) // a b d c
minAvailableModulesOwned: true
resultingAvailableModules: undefined
skippedItems: Array(1) // b
}
}
]
绗簩闃舵 connectChunkGroups
chunkDependencies
鍙繚瀛樻湁瀛?chunkGroup 鐨?chunkGroup(涔熷氨鏄?EntryPoint 鍜岋紝鏈夊紓姝ヤ緷璧栫殑寮傛妯″潡鍒涘缓鐨?chunkGroup 鎵嶄細琚瓨鍒伴噷闈? 锛屽睘鎬ф槸 chunkGroup锛?鍊兼槸 chunkGroup 鐨勬墍鏈?瀛?chunkGroup 鍜?寮傛渚濊禆缁勬垚鐨勫璞?鐨勬暟缁勶細// chunkDependencies Map 瀵硅薄
[
0: {
key: Entrypoint, // groupDebugId: 5000
value: [
{ block: ImportDependenciesBlock, chunkGroup: ChunkGroup }, // groupDebugId: 5001
// { block: ImportDependenciesBlock, chunkGroup: ChunkGroup }, // groupDebugId: 5003
// 瀹為檯椤圭洰涓€鑸細瀛樺湪澶氶」
]
},
1: {
key: ChunkGroup, // groupDebugId: 5001
value: [
{ block: ImportDependenciesBlock, chunkGroup: ChunkGroup } // groupDebugId: 5002
]
},
]
// 绠€鍗曞湴鐢? groupDebugId 鎸囦唬瀛?chunkgroup 鍜?瀛?chunkgroup 鐨?chunk
{
{ key: EntryPoint 5000, value: [5001, 5002, 5003, 5004] },
{ key: ChunkGroup 5001, value: [5005, 5006] },
{ key: ChunkGroup 5002, value: [5007] }
}
chunkGroup
鍜?code>_blocks)銆佺埗 chunkGroup 鍜屽瓙 chunkGroup 鐨勭埗瀛愬叧绯?浜掔浉娣诲姞鍒板郊姝ょ殑_children
鍜?code>_parents)锛?br>
(resultingAvailableModules
閫氳繃鏌ヨchunkGroupInfoMap.get(鐖禼hunkGroup)
鑾峰彇)
濡備笂闈?demo2锛孋hunkGroup 5001 鐨勫彲鐢ㄦā鍧楁槸a b d e c j
锛屽畠鐨勫瓙 ChunkGroup 5005 鏄敱 b 鍒涘缓鐨?涓斿洜涓轰笉浼氶噸澶嶅垱寤哄叆鍙?chunk 涓瓨鍦ㄧ殑鍚屾妯″潡锛?5005 鐨?chunk 骞朵笉鍖呭惈浠讳綍妯″潡)锛屾病鏈夋柊妯″潡锛屾晠鑰屾病鏈夊缓绔嬭捣鍏崇郴銆傝€屽瓙ChunkGroup 5006 鏈夋柊妯″潡 k锛屽氨寤虹珛璧蜂簡涓婅堪鍏崇郴銆?/p>
// /lib/buildChunkGraph.js
// ImportDependenciesBlock 涓?chunkGroup 寤虹珛鑱旂郴锛屼簰鐩告坊鍔犲埌褰兼鐨?chunkGroup 鍜?_blocks
GraphHelpers.connectDependenciesBlockAndChunkGroup(
depBlock,
depChunkGroup
);
// chunkGroup 涔嬮棿寤虹珛鑱旂郴锛氫簰鐩告坊鍔犲埌褰兼鐨?_children 鍜?_parents
GraphHelpers.connectChunkGroupParentAndChild(
chunkGroup,
depChunkGroup
);
绗笁闃舵 cleanupUnconnectedGroups
娓呯悊鏃犵敤 chunk 骞舵竻鐞嗙浉鍏崇殑鑱旂郴銆?br>
閫氳繃閬嶅巻allCreatedChunkGroups
锛屽鏋滈亣鍒板湪绗簩闃舵娌℃湁寤虹珛璧疯仈绯荤殑 chunkGroup(濡備笂闈?demo2 chunkGroup 5005)锛岄偅涔堝氨灏嗚繖浜?chunkGroup 涓殑鎵€鏈?chunk 浠?chunk graph 渚濊禆鍥惧綋涓墧闄ゆ帀 ( demo2 涓殑寮傛 b chunk 姝ゆ椂琚垹闄?)銆?br>
allCreatedChunkGroups
鍗冲紓姝ユā鍧楄鍒涘缓鐨?chunkGroup锛屼緷娆″垽鏂?chunkGroup 鏈夋棤鐖?chunkGroup(_parents
)锛屾病鏈夊垯鎵ц锛?/p>
// /lib/buildChunkGraph.js
for (const chunk of chunkGroup.chunks) {
const idx = compilation.chunks.indexOf(chunk);
if (idx >= 0) compilation.chunks.splice(idx, 1); // 鍒犻櫎 chunk
chunk.remove('unconnected');
}
chunkGroup.remove('unconnected');
鍚屾椂瑙i櫎 module銆乧hunk銆乧hunkGroup 涓夎€呬箣闂寸殑鑱旂郴銆?/p>
鏈€缁堟瘡涓?module 涓庢瘡涓?chunk銆佹瘡涓?chunkGroup 涔嬮棿閮藉缓绔嬩簡鑱旂郴锛屼紭鍖栧舰鎴愪簡 chunk graph銆?/p>
buildChunkGraph 涓夐樁娈垫€荤粨锛?br> 1.
visitModules
锛氫负鍏ュ彛妯″潡鍜屽畠鎵€鏈?鐩存帴/闂存帴)鍚屾渚濊禆褰㈡垚涓€涓?EntryPoint(缁ф壙鑷?ChunkGroup)锛屼负鎵€鏈夊紓姝ユā鍧楀拰瀹冪殑鍚屾渚濊禆鐢熸垚涓€涓?chunk 鍜?chunkGroup(浼氶噸澶?銆傚 chunk 鐨勫悓姝ユā鍧楀凡瀛樺湪浜庡叆鍙?chunk锛屽垯涓嶄細鍐嶅瓨鍏ュ畠鐨?code>_modules銆傛闃舵鍒濆鐢熸垚浜?chunk graph(chunk 渚濊禆鍥?銆?br> 2.connectChunkGroups
锛氭鏌ュ叆鍙?chunk 鍜?鏈夊紓姝ヤ緷璧栫殑寮傛 chunk, 濡傛灉瀹冧滑鐨勫瓙 chunk 鏈夊畠浠湭鍖呭惈鐨勬柊妯″潡锛屽氨寤虹珛瀹冧滑鍚勮嚜鎵€灞?chunkGroup 鐨?鐖跺瓙鍏崇郴銆?br> 3.cleanupUnconnectedGroups
锛氭壘鍒版病鏈夌埗 chunkgroup 鐨?chunkgroup锛屽垹闄ゅ畠閲岄潰鐨?chunk锛屽苟瑙i櫎涓庣浉鍏?module銆乧hunk銆乧hunkGroup 鐨勫叧绯汇€?br> 2銆? 闃舵瀵?chunk graph 杩涜浜嗕紭鍖栵紝鍘婚櫎浜?鐢卞凡瀛樺湪浜庡叆鍙?chunk 涓殑 妯″潡鍒涘缓鐨勫紓姝?chunk銆?/p>
鍥炲埌 Compilation.js锛宑ompilation 鐨?seal 鏂规硶缁х画鎵ц锛屽厛灏?compilation.modules 鎸?index 灞炴€уぇ灏忔帓搴忥紝鐒跺悗鎵ц锛?strong>this.hooks.afterChunks.call(this.chunks)
銆傝Е鍙戞彃浠?WebAssemblyModulesPlugin锛氳缃笌 webassembly 鐩稿叧鐨勬姤閿欎俊鎭紝鍒版 chunk 鐢熸垚缁撴潫銆?/p>
5.3 module銆乧hunk銆乧hunkGroup 瀛樺偍瀛楁鐩稿叧
module
module 鍗虫瘡涓€涓祫婧愭枃浠剁殑妯″潡瀵瑰簲锛屽 js/css/鍥剧墖 绛夈€傜敱 NormalModule 瀹炰緥鍖栬€屾潵锛屽瓨浜?strong>compilation.modules
鏁扮粍銆?/p>
-
module.blocks
锛歮odule 鐨勫紓姝ヤ緷璧?/li> -
module.dependencies
锛歮odule 鐨勫悓姝ヤ緷璧?/li> -
module._chunks
锛歮odule 鎵€灞?chunk 鍒楄〃
chunk
姣忎竴涓緭鍑烘枃浠剁殑瀵瑰簲锛屾瘮濡傚叆鍙f枃浠躲€佸紓姝ュ姞杞芥枃浠躲€佷紭鍖栧垏鍓插悗鐨勬枃浠剁瓑绛夛紝瀛樹簬compilation.chunks
鏁扮粍銆?/p>
-
chunk._groups
锛歝hunk 鎵€灞炵殑 chunkGroup 鍒楄〃 -
chunk._modules
锛氱敱鍝簺 module 缁勬垚
chunkGroup
榛樿鎯呭喌涓嬶紝姣忎釜 chunkGroup 閮藉彧鍖呭惈涓€涓?chunk锛氫富 chunkGroup (EntryPoint) 鍖呭惈鍏ュ彛 chunk锛屽叾浣?chunkGroup 鍚勫寘鍚竴涓紓姝ユā鍧?chunk銆傚瓨浜?strong>compilation.chunkGroups
鏁扮粍銆?br>
褰撻厤缃簡optimization.splitChunks
锛孲plitChunksPlugin 鎻掍欢灏嗗叆鍙?chunk 鎷嗗垎涓哄涓悓姝?chunk锛岄偅涔堜富 ChunkGroup (EntryPoint) 灏变細鏈夊涓?chunk 浜嗐€傚彟澶栵紝濡?runtime 琚崟鐙娊鎴愪竴涓枃浠讹紝閭d箞 EntryPoint 灏变細澶氬嚭涓€涓?runtime chunk銆?/p>
-
chunkGroup.chunks
锛氱敱鍝簺 chunk 缁勬垚 -
chunkGroup._blocks
锛氬紓姝ヤ緷璧?ImportDependenciesBlock -
chunkGroup._children
锛氬瓙 chunkGroup -
chunkGroup._parent
锛氱埗 chunkGroup
涓嬫枃锛氭祬鏋?webpack 鎵撳寘娴佺▼(鍘熺悊) 鍥?- chunk 浼樺寲
webpack 鎵撳寘娴佺▼绯诲垪(鏈畬)锛?br>
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) - 妗堜緥 demo
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 涓€ - 鍑嗗宸ヤ綔
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 浜?- 閫掑綊鏋勫缓 module
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 涓?- 鐢熸垚 chunk
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 鍥?- chunk 浼樺寲
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 浜?- 鏋勫缓璧勬簮
娴呮瀽 webpack 鎵撳寘娴佺▼(鍘熺悊) 鍏?- 鐢熸垚鏂囦欢
鍙傝€冮福璋細
webpack鎵撳寘鍘熺悊 鐪嬪畬杩欑瘒浣犲氨鎳備簡 !
webpack 閫忚鈥斺€旀彁楂樺伐绋嬪寲锛堝師鐞嗙瘒锛?br>
webpack 閫忚鈥斺€旀彁楂樺伐绋嬪寲锛堝疄璺电瘒锛?br>
webpack 4 婧愮爜涓绘祦绋嬪垎鏋?br>
[涓囧瓧鎬荤粨] 涓€鏂囧悆閫?Webpack 鏍稿績鍘熺悊
鏈夌偣闅剧殑 Webpack 鐭ヨ瘑鐐癸細Dependency Graph 娣卞害瑙f瀽
webpack绯诲垪涔嬪叚chunk鍥剧敓鎴?/p>