| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-01 02:52:50 +08:00
										 |  |  | const crypto = require("crypto"); | 
					
						
							| 
									
										
										
										
											2018-07-31 04:30:27 +08:00
										 |  |  | const { STAGE_ADVANCED } = require("../OptimizationStages"); | 
					
						
							| 
									
										
										
										
											2018-08-25 03:06:52 +08:00
										 |  |  | const WebpackError = require("../WebpackError"); | 
					
						
							| 
									
										
										
										
											2018-03-22 19:05:58 +08:00
										 |  |  | const { isSubset } = require("../util/SetHelpers"); | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | const SortableSet = require("../util/SortableSet"); | 
					
						
							| 
									
										
										
										
											2018-08-28 21:07:28 +08:00
										 |  |  | const { | 
					
						
							|  |  |  | 	compareModulesByIdentifier, | 
					
						
							|  |  |  | 	compareIterables | 
					
						
							|  |  |  | } = require("../util/comparators"); | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | const deterministicGrouping = require("../util/deterministicGrouping"); | 
					
						
							|  |  |  | const contextify = require("../util/identifier").contextify; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | /** @typedef {import("../Chunk")} Chunk */ | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | /** @typedef {import("../ChunkGraph")} ChunkGraph */ | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:06 +08:00
										 |  |  | /** @typedef {import("../Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | /** @typedef {import("../Module")} Module */ | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | /** @typedef {import("../ModuleGraph")} ModuleGraph */ | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | /** @typedef {import("../util/deterministicGrouping").GroupedItems<Module>} DeterministicGroupingGroupedItemsForModule */ | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:06 +08:00
										 |  |  | /** @typedef {import("../util/deterministicGrouping").Options<Module>} DeterministicGroupingOptionsForModule */ | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 17:50:33 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} ChunksInfoItem | 
					
						
							|  |  |  |  * @property {SortableSet<Module>} modules | 
					
						
							|  |  |  |  * @property {TODO} cacheGroup | 
					
						
							|  |  |  |  * @property {string} name | 
					
						
							|  |  |  |  * @property {number} size | 
					
						
							|  |  |  |  * @property {Set<Chunk>} chunks | 
					
						
							|  |  |  |  * @property {Set<Chunk>} reuseableChunks | 
					
						
							|  |  |  |  * @property {Set<string>} chunksKeys | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | const deterministicGroupingForModules = /** @type {function(DeterministicGroupingOptionsForModule): DeterministicGroupingGroupedItemsForModule[]} */ (deterministicGrouping); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | const hashFilename = name => { | 
					
						
							|  |  |  | 	return crypto | 
					
						
							|  |  |  | 		.createHash("md4") | 
					
						
							|  |  |  | 		.update(name) | 
					
						
							|  |  |  | 		.digest("hex") | 
					
						
							|  |  |  | 		.slice(0, 8); | 
					
						
							| 
									
										
										
										
											2018-02-01 02:52:50 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | const getRequests = chunk => { | 
					
						
							|  |  |  | 	let requests = 0; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	for (const chunkGroup of chunk.groupsIterable) { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		requests = Math.max(requests, chunkGroup.chunks.length); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return requests; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const getModulesSize = modules => { | 
					
						
							|  |  |  | 	let sum = 0; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 	for (const m of modules) { | 
					
						
							|  |  |  | 		sum += m.size(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	return sum; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @template T | 
					
						
							|  |  |  |  * @param {Set<T>} a set | 
					
						
							|  |  |  |  * @param {Set<T>} b other set | 
					
						
							|  |  |  |  * @returns {boolean} true if at least one item of a is in b | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | const isOverlap = (a, b) => { | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 	for (const item of a) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (b.has(item)) return true; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 21:07:28 +08:00
										 |  |  | const compareModuleIterables = compareIterables(compareModulesByIdentifier); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 17:50:33 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {ChunksInfoItem} a item | 
					
						
							|  |  |  |  * @param {ChunksInfoItem} b item | 
					
						
							|  |  |  |  * @returns {number} compare result | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | const compareEntries = (a, b) => { | 
					
						
							| 
									
										
										
										
											2018-01-20 20:11:02 +08:00
										 |  |  | 	// 1. by priority
 | 
					
						
							|  |  |  | 	const diffPriority = a.cacheGroup.priority - b.cacheGroup.priority; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	if (diffPriority) return diffPriority; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 	// 2. by number of chunks
 | 
					
						
							|  |  |  | 	const diffCount = a.chunks.size - b.chunks.size; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	if (diffCount) return diffCount; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 	// 3. by size reduction
 | 
					
						
							|  |  |  | 	const aSizeReduce = a.size * (a.chunks.size - 1); | 
					
						
							|  |  |  | 	const bSizeReduce = b.size * (b.chunks.size - 1); | 
					
						
							|  |  |  | 	const diffSizeReduce = aSizeReduce - bSizeReduce; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	if (diffSizeReduce) return diffSizeReduce; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 	// 4. by number of modules (to be able to compare by identifier)
 | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	const modulesA = a.modules; | 
					
						
							|  |  |  | 	const modulesB = b.modules; | 
					
						
							|  |  |  | 	const diff = modulesA.size - modulesB.size; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 	if (diff) return diff; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 	// 5. by module identifiers
 | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	modulesA.sort(); | 
					
						
							|  |  |  | 	modulesB.sort(); | 
					
						
							| 
									
										
										
										
											2018-08-28 21:07:28 +08:00
										 |  |  | 	// TODO logic is inverted: fix this
 | 
					
						
							|  |  |  | 	return compareModuleIterables(modulesB, modulesA); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | const INITIAL_CHUNK_FILTER = chunk => chunk.canBeInitial(); | 
					
						
							|  |  |  | const ASYNC_CHUNK_FILTER = chunk => !chunk.canBeInitial(); | 
					
						
							|  |  |  | const ALL_CHUNK_FILTER = chunk => true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | module.exports = class SplitChunksPlugin { | 
					
						
							|  |  |  | 	constructor(options) { | 
					
						
							|  |  |  | 		this.options = SplitChunksPlugin.normalizeOptions(options); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-02 08:09:01 +08:00
										 |  |  | 	static normalizeOptions(options = {}) { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 			chunksFilter: SplitChunksPlugin.normalizeChunksFilter( | 
					
						
							|  |  |  | 				options.chunks || "all" | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			minSize: options.minSize || 0, | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 			maxSize: options.maxSize || 0, | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			minChunks: options.minChunks || 1, | 
					
						
							|  |  |  | 			maxAsyncRequests: options.maxAsyncRequests || 1, | 
					
						
							|  |  |  | 			maxInitialRequests: options.maxInitialRequests || 1, | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 			hidePathInfo: options.hidePathInfo || false, | 
					
						
							| 
									
										
										
										
											2018-03-02 17:14:25 +08:00
										 |  |  | 			filename: options.filename || undefined, | 
					
						
							| 
									
										
										
										
											2018-03-09 21:27:19 +08:00
										 |  |  | 			getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({ | 
					
						
							|  |  |  | 				cacheGroups: options.cacheGroups, | 
					
						
							| 
									
										
										
										
											2018-07-02 16:15:13 +08:00
										 |  |  | 				name: options.name, | 
					
						
							| 
									
										
										
										
											2018-03-12 17:07:31 +08:00
										 |  |  | 				automaticNameDelimiter: options.automaticNameDelimiter | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 			}), | 
					
						
							| 
									
										
										
										
											2018-07-05 19:19:55 +08:00
										 |  |  | 			automaticNameDelimiter: options.automaticNameDelimiter, | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 			fallbackCacheGroup: SplitChunksPlugin.normalizeFallbackCacheGroup( | 
					
						
							|  |  |  | 				options.fallbackCacheGroup || {}, | 
					
						
							|  |  |  | 				options | 
					
						
							|  |  |  | 			) | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 16:15:13 +08:00
										 |  |  | 	static normalizeName({ name, automaticNameDelimiter, automaticNamePrefix }) { | 
					
						
							| 
									
										
										
										
											2018-03-12 17:07:31 +08:00
										 |  |  | 		if (name === true) { | 
					
						
							| 
									
										
										
										
											2018-07-05 18:50:51 +08:00
										 |  |  | 			/** @type {WeakMap<Chunk[], Record<string, string>>} */ | 
					
						
							|  |  |  | 			const cache = new WeakMap(); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			const fn = (module, chunks, cacheGroup) => { | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 				let cacheEntry = cache.get(chunks); | 
					
						
							|  |  |  | 				if (cacheEntry === undefined) { | 
					
						
							|  |  |  | 					cacheEntry = {}; | 
					
						
							|  |  |  | 					cache.set(chunks, cacheEntry); | 
					
						
							|  |  |  | 				} else if (cacheGroup in cacheEntry) { | 
					
						
							|  |  |  | 					return cacheEntry[cacheGroup]; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				const names = chunks.map(c => c.name); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 				if (!names.every(Boolean)) { | 
					
						
							|  |  |  | 					cacheEntry[cacheGroup] = undefined; | 
					
						
							|  |  |  | 					return; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				names.sort(); | 
					
						
							| 
									
										
										
										
											2018-07-02 16:15:13 +08:00
										 |  |  | 				const prefix = | 
					
						
							|  |  |  | 					typeof automaticNamePrefix === "string" | 
					
						
							|  |  |  | 						? automaticNamePrefix | 
					
						
							|  |  |  | 						: cacheGroup; | 
					
						
							|  |  |  | 				const namePrefix = prefix ? prefix + automaticNameDelimiter : ""; | 
					
						
							|  |  |  | 				let name = namePrefix + names.join(automaticNameDelimiter); | 
					
						
							| 
									
										
										
										
											2018-02-01 02:52:50 +08:00
										 |  |  | 				// Filenames and paths can't be too long otherwise an
 | 
					
						
							|  |  |  | 				// ENAMETOOLONG error is raised. If the generated name if too
 | 
					
						
							|  |  |  | 				// long, it is truncated and a hash is appended. The limit has
 | 
					
						
							|  |  |  | 				// been set to 100 to prevent `[name].[chunkhash].[ext]` from
 | 
					
						
							|  |  |  | 				// generating a 256+ character string.
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (name.length > 100) { | 
					
						
							| 
									
										
										
										
											2018-03-09 21:27:19 +08:00
										 |  |  | 					name = | 
					
						
							| 
									
										
										
										
											2018-03-12 17:07:31 +08:00
										 |  |  | 						name.slice(0, 100) + automaticNameDelimiter + hashFilename(name); | 
					
						
							| 
									
										
										
										
											2018-02-01 02:52:50 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 				cacheEntry[cacheGroup] = name; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				return name; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			return fn; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-12 17:32:46 +08:00
										 |  |  | 		if (typeof name === "string") { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			const fn = () => { | 
					
						
							| 
									
										
										
										
											2018-03-12 17:07:31 +08:00
										 |  |  | 				return name; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			}; | 
					
						
							|  |  |  | 			return fn; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-12 17:32:46 +08:00
										 |  |  | 		if (typeof name === "function") return name; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 	static normalizeChunksFilter(chunks) { | 
					
						
							|  |  |  | 		if (chunks === "initial") { | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 			return INITIAL_CHUNK_FILTER; | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (chunks === "async") { | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 			return ASYNC_CHUNK_FILTER; | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (chunks === "all") { | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 			return ALL_CHUNK_FILTER; | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (typeof chunks === "function") return chunks; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 	static normalizeFallbackCacheGroup( | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			minSize = undefined, | 
					
						
							|  |  |  | 			maxSize = undefined, | 
					
						
							|  |  |  | 			automaticNameDelimiter = undefined | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			minSize: defaultMinSize = undefined, | 
					
						
							|  |  |  | 			maxSize: defaultMaxSize = undefined, | 
					
						
							|  |  |  | 			automaticNameDelimiter: defaultAutomaticNameDelimiter = undefined | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	) { | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			minSize: typeof minSize === "number" ? minSize : defaultMinSize || 0, | 
					
						
							|  |  |  | 			maxSize: typeof maxSize === "number" ? maxSize : defaultMaxSize || 0, | 
					
						
							|  |  |  | 			automaticNameDelimiter: | 
					
						
							|  |  |  | 				automaticNameDelimiter || defaultAutomaticNameDelimiter || "~" | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 16:15:13 +08:00
										 |  |  | 	static normalizeCacheGroups({ cacheGroups, name, automaticNameDelimiter }) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (typeof cacheGroups === "function") { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			return cacheGroups; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (cacheGroups && typeof cacheGroups === "object") { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 			const fn = (module, context) => { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				let results; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				for (const key of Object.keys(cacheGroups)) { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 					let option = cacheGroups[key]; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (option === false) continue; | 
					
						
							|  |  |  | 					if (option instanceof RegExp || typeof option === "string") { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 						option = { | 
					
						
							|  |  |  | 							test: option | 
					
						
							|  |  |  | 						}; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (typeof option === "function") { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 						let result = option(module); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						if (result) { | 
					
						
							|  |  |  | 							if (results === undefined) results = []; | 
					
						
							|  |  |  | 							for (const r of Array.isArray(result) ? result : [result]) { | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 								const result = Object.assign({ key }, r); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								if (result.name) result.getName = () => result.name; | 
					
						
							| 
									
										
										
										
											2018-03-21 03:57:02 +08:00
										 |  |  | 								if (result.chunks) { | 
					
						
							|  |  |  | 									result.chunksFilter = SplitChunksPlugin.normalizeChunksFilter( | 
					
						
							|  |  |  | 										result.chunks | 
					
						
							|  |  |  | 									); | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 								results.push(result); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					} else if ( | 
					
						
							| 
									
										
										
										
											2018-08-25 01:46:07 +08:00
										 |  |  | 						SplitChunksPlugin.checkTest(option.test, module, context) && | 
					
						
							|  |  |  | 						SplitChunksPlugin.checkModuleType(option.type, module) | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						if (results === undefined) results = []; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 						results.push({ | 
					
						
							|  |  |  | 							key: key, | 
					
						
							| 
									
										
										
										
											2018-01-20 20:11:02 +08:00
										 |  |  | 							priority: option.priority, | 
					
						
							| 
									
										
										
										
											2018-07-02 16:15:13 +08:00
										 |  |  | 							getName: | 
					
						
							|  |  |  | 								SplitChunksPlugin.normalizeName({ | 
					
						
							|  |  |  | 									name: option.name || name, | 
					
						
							|  |  |  | 									automaticNameDelimiter: | 
					
						
							|  |  |  | 										typeof option.automaticNameDelimiter === "string" | 
					
						
							|  |  |  | 											? option.automaticNameDelimiter | 
					
						
							|  |  |  | 											: automaticNameDelimiter, | 
					
						
							|  |  |  | 									automaticNamePrefix: option.automaticNamePrefix | 
					
						
							|  |  |  | 								}) || (() => {}), | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 							chunksFilter: SplitChunksPlugin.normalizeChunksFilter( | 
					
						
							|  |  |  | 								option.chunks | 
					
						
							|  |  |  | 							), | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							enforce: option.enforce, | 
					
						
							|  |  |  | 							minSize: option.minSize, | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 							maxSize: option.maxSize, | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							minChunks: option.minChunks, | 
					
						
							|  |  |  | 							maxAsyncRequests: option.maxAsyncRequests, | 
					
						
							|  |  |  | 							maxInitialRequests: option.maxInitialRequests, | 
					
						
							| 
									
										
										
										
											2018-03-02 17:14:25 +08:00
										 |  |  | 							filename: option.filename, | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							reuseExistingChunk: option.reuseExistingChunk | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return results; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			return fn; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		const fn = () => {}; | 
					
						
							|  |  |  | 		return fn; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @typedef {Object} TestContext | 
					
						
							|  |  |  | 	 * @property {ModuleGraph} moduleGraph the module graph | 
					
						
							|  |  |  | 	 * @property {ChunkGraph} chunkGraph the chunk graph | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {undefined|boolean|string|RegExp|function(Module, TestContext): boolean} test test option | 
					
						
							|  |  |  | 	 * @param {Module} module the module | 
					
						
							|  |  |  | 	 * @param {TestContext} context context object | 
					
						
							|  |  |  | 	 * @returns {boolean} true, if the module should be selected | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	static checkTest(test, module, context) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (test === undefined) return true; | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 		if (typeof test === "function") { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 			return test(module, context); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (typeof test === "boolean") return test; | 
					
						
							|  |  |  | 		if (typeof test === "string") { | 
					
						
							| 
									
										
										
										
											2018-07-25 18:12:17 +08:00
										 |  |  | 			const name = module.nameForCondition(); | 
					
						
							| 
									
										
										
										
											2018-08-25 03:06:52 +08:00
										 |  |  | 			return name && name.startsWith(test); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		if (test instanceof RegExp) { | 
					
						
							| 
									
										
										
										
											2018-07-25 18:12:17 +08:00
										 |  |  | 			const name = module.nameForCondition(); | 
					
						
							| 
									
										
										
										
											2018-08-25 03:06:52 +08:00
										 |  |  | 			return name && test.test(name); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-25 01:46:07 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {undefined|string|RegExp|function(string): boolean} test type option | 
					
						
							|  |  |  | 	 * @param {Module} module the module | 
					
						
							|  |  |  | 	 * @returns {boolean} true, if the module should be selected | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	static checkModuleType(test, module) { | 
					
						
							|  |  |  | 		if (test === undefined) return true; | 
					
						
							|  |  |  | 		if (typeof test === "function") { | 
					
						
							|  |  |  | 			return test(module.type); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (typeof test === "string") { | 
					
						
							|  |  |  | 			const type = module.type; | 
					
						
							|  |  |  | 			return test === type; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (test instanceof RegExp) { | 
					
						
							|  |  |  | 			const type = module.type; | 
					
						
							|  |  |  | 			return test.test(type); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {Compiler} compiler webpack compiler | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2018-01-24 19:00:50 +08:00
										 |  |  | 		compiler.hooks.thisCompilation.tap("SplitChunksPlugin", compilation => { | 
					
						
							| 
									
										
										
										
											2018-01-20 20:11:02 +08:00
										 |  |  | 			let alreadyOptimized = false; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			compilation.hooks.unseal.tap("SplitChunksPlugin", () => { | 
					
						
							| 
									
										
										
										
											2018-01-20 20:11:02 +08:00
										 |  |  | 				alreadyOptimized = false; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2018-07-31 04:30:27 +08:00
										 |  |  | 			compilation.hooks.optimizeChunks.tap( | 
					
						
							|  |  |  | 				/** @type {TODO} */ ({ | 
					
						
							|  |  |  | 					name: "SplitChunksPlugin", | 
					
						
							|  |  |  | 					stage: STAGE_ADVANCED | 
					
						
							|  |  |  | 				}), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				chunks => { | 
					
						
							|  |  |  | 					if (alreadyOptimized) return; | 
					
						
							|  |  |  | 					alreadyOptimized = true; | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					const chunkGraph = compilation.chunkGraph; | 
					
						
							|  |  |  | 					const moduleGraph = compilation.moduleGraph; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Give each selected chunk an index (to create strings from chunks)
 | 
					
						
							|  |  |  | 					const indexMap = new Map(); | 
					
						
							|  |  |  | 					let index = 1; | 
					
						
							|  |  |  | 					for (const chunk of chunks) { | 
					
						
							|  |  |  | 						indexMap.set(chunk, index++); | 
					
						
							| 
									
										
										
										
											2018-02-17 16:48:40 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					const getKey = chunks => { | 
					
						
							|  |  |  | 						return Array.from(chunks, c => indexMap.get(c)) | 
					
						
							|  |  |  | 							.sort() | 
					
						
							|  |  |  | 							.join(); | 
					
						
							|  |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 					/** @type {Map<string, Set<Chunk>>} */ | 
					
						
							|  |  |  | 					const chunkSetsInGraph = new Map(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					for (const module of compilation.modules) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						const chunksKey = getKey( | 
					
						
							|  |  |  | 							chunkGraph.getModuleChunksIterable(module) | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 						if (!chunkSetsInGraph.has(chunksKey)) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 							chunkSetsInGraph.set( | 
					
						
							|  |  |  | 								chunksKey, | 
					
						
							|  |  |  | 								new Set(chunkGraph.getModuleChunksIterable(module)) | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// group these set of chunks by count
 | 
					
						
							|  |  |  | 					// to allow to check less sets via isSubset
 | 
					
						
							|  |  |  | 					// (only smaller sets can be subset)
 | 
					
						
							|  |  |  | 					/** @type {Map<number, Array<Set<Chunk>>>} */ | 
					
						
							|  |  |  | 					const chunkSetsByCount = new Map(); | 
					
						
							|  |  |  | 					for (const chunksSet of chunkSetsInGraph.values()) { | 
					
						
							|  |  |  | 						const count = chunksSet.size; | 
					
						
							|  |  |  | 						let array = chunkSetsByCount.get(count); | 
					
						
							|  |  |  | 						if (array === undefined) { | 
					
						
							|  |  |  | 							array = []; | 
					
						
							|  |  |  | 							chunkSetsByCount.set(count, array); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 						array.push(chunksSet); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// Create a list of possible combinations
 | 
					
						
							|  |  |  | 					const combinationsCache = new Map(); // Map<string, Set<Chunk>[]>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					const getCombinations = key => { | 
					
						
							|  |  |  | 						const chunksSet = chunkSetsInGraph.get(key); | 
					
						
							|  |  |  | 						var array = [chunksSet]; | 
					
						
							|  |  |  | 						if (chunksSet.size > 1) { | 
					
						
							|  |  |  | 							for (const [count, setArray] of chunkSetsByCount) { | 
					
						
							|  |  |  | 								// "equal" is not needed because they would have been merge in the first step
 | 
					
						
							|  |  |  | 								if (count < chunksSet.size) { | 
					
						
							|  |  |  | 									for (const set of setArray) { | 
					
						
							|  |  |  | 										if (isSubset(chunksSet, set)) { | 
					
						
							|  |  |  | 											array.push(set); | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return array; | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 					/** | 
					
						
							|  |  |  | 					 * @typedef {Object} SelectedChunksResult | 
					
						
							|  |  |  | 					 * @property {Chunk[]} chunks the list of chunks | 
					
						
							|  |  |  | 					 * @property {string} key a key of the list | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * @typedef {function(Chunk): boolean} ChunkFilterFunction | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** @type {WeakMap<Set<Chunk>, WeakMap<ChunkFilterFunction, SelectedChunksResult>>} */ | 
					
						
							|  |  |  | 					const selectedChunksCacheByChunksSet = new WeakMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** | 
					
						
							|  |  |  | 					 * get list and key by applying the filter function to the list | 
					
						
							|  |  |  | 					 * It is cached for performance reasons | 
					
						
							|  |  |  | 					 * @param {Set<Chunk>} chunks list of chunks | 
					
						
							|  |  |  | 					 * @param {ChunkFilterFunction} chunkFilter filter function for chunks | 
					
						
							|  |  |  | 					 * @returns {SelectedChunksResult} list and key | 
					
						
							|  |  |  | 					 */ | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 					const getSelectedChunks = (chunks, chunkFilter) => { | 
					
						
							|  |  |  | 						let entry = selectedChunksCacheByChunksSet.get(chunks); | 
					
						
							|  |  |  | 						if (entry === undefined) { | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							entry = new WeakMap(); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 							selectedChunksCacheByChunksSet.set(chunks, entry); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						/** @type {SelectedChunksResult} */ | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 						let entry2 = entry.get(chunkFilter); | 
					
						
							|  |  |  | 						if (entry2 === undefined) { | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							/** @type {Chunk[]} */ | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 							const selectedChunks = []; | 
					
						
							|  |  |  | 							for (const chunk of chunks) { | 
					
						
							|  |  |  | 								if (chunkFilter(chunk)) selectedChunks.push(chunk); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							entry2 = { | 
					
						
							|  |  |  | 								chunks: selectedChunks, | 
					
						
							|  |  |  | 								key: getKey(selectedChunks) | 
					
						
							|  |  |  | 							}; | 
					
						
							|  |  |  | 							entry.set(chunkFilter, entry2); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return entry2; | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-25 03:06:52 +08:00
										 |  |  | 					/** | 
					
						
							|  |  |  | 					 * @typedef {Object} ChunksInfoItem | 
					
						
							|  |  |  | 					 * @property {SortableSet} modules | 
					
						
							|  |  |  | 					 * @property {TODO} cacheGroup | 
					
						
							|  |  |  | 					 * @property {string} name | 
					
						
							|  |  |  | 					 * @property {number} size | 
					
						
							|  |  |  | 					 * @property {Set<Chunk>} chunks | 
					
						
							|  |  |  | 					 * @property {Set<Chunk>} reuseableChunks | 
					
						
							|  |  |  | 					 * @property {Set<string>} chunksKeys | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/** @type {Set<string>} */ | 
					
						
							|  |  |  | 					const alreadyValidatedNames = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Map a list of chunks to a list of modules
 | 
					
						
							|  |  |  | 					// For the key the chunk "index" is used, the value is a SortableSet of modules
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 					/** @type {Map<string, ChunksInfoItem>} */ | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					const chunksInfoMap = new Map(); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 					/** | 
					
						
							|  |  |  | 					 * @param {TODO} cacheGroup the current cache group | 
					
						
							|  |  |  | 					 * @param {Chunk[]} selectedChunks chunks selected for this module | 
					
						
							|  |  |  | 					 * @param {string} selectedChunksKey a key of selectedChunks | 
					
						
							|  |  |  | 					 * @param {Module} module the current module | 
					
						
							|  |  |  | 					 * @returns {void} | 
					
						
							|  |  |  | 					 */ | 
					
						
							|  |  |  | 					const addModuleToChunksInfoMap = ( | 
					
						
							|  |  |  | 						cacheGroup, | 
					
						
							|  |  |  | 						selectedChunks, | 
					
						
							|  |  |  | 						selectedChunksKey, | 
					
						
							|  |  |  | 						module | 
					
						
							|  |  |  | 					) => { | 
					
						
							|  |  |  | 						// Break if minimum number of chunks is not reached
 | 
					
						
							|  |  |  | 						if (selectedChunks.length < cacheGroup.minChunks) return; | 
					
						
							|  |  |  | 						// Determine name for split chunk
 | 
					
						
							|  |  |  | 						const name = cacheGroup.getName( | 
					
						
							|  |  |  | 							module, | 
					
						
							|  |  |  | 							selectedChunks, | 
					
						
							|  |  |  | 							cacheGroup.key | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2018-08-25 03:06:52 +08:00
										 |  |  | 						// Check if the name is ok
 | 
					
						
							|  |  |  | 						if (!alreadyValidatedNames.has(name)) { | 
					
						
							|  |  |  | 							alreadyValidatedNames.add(name); | 
					
						
							|  |  |  | 							if (compilation.namedChunks.has(name)) { | 
					
						
							|  |  |  | 								compilation.errors.push( | 
					
						
							|  |  |  | 									new WebpackError( | 
					
						
							|  |  |  | 										"SplitChunksPlugin\n" + | 
					
						
							|  |  |  | 											`Cache group "${ | 
					
						
							|  |  |  | 												cacheGroup.key | 
					
						
							|  |  |  | 											}" conflicts with existing chunk.\n` +
 | 
					
						
							|  |  |  | 											`Both have the same name "${name}".\n` + | 
					
						
							|  |  |  | 											"Use a different name for the cache group.\n" + | 
					
						
							|  |  |  | 											'HINT: You can omit "name" to automatically create a name.\n' + | 
					
						
							|  |  |  | 											"BREAKING CHANGE: webpack < 5 used to allow to use the " + | 
					
						
							|  |  |  | 											"entrypoint as splitChunk. This is no longer allowed. " + | 
					
						
							|  |  |  | 											"Remove this entrypoint and add modules to cache group's 'test' instead. " + | 
					
						
							|  |  |  | 											"If you need modules to be evaluated on startup, add them to the existing entrypoints (make them arrays). " + | 
					
						
							|  |  |  | 											"See migration guide of more info." | 
					
						
							|  |  |  | 									) | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						// Create key for maps
 | 
					
						
							|  |  |  | 						// When it has a name we use the name as key
 | 
					
						
							|  |  |  | 						// Elsewise we create the key from chunks and cache group key
 | 
					
						
							|  |  |  | 						// This automatically merges equal names
 | 
					
						
							|  |  |  | 						const key = | 
					
						
							|  |  |  | 							(name && `name:${name}`) || | 
					
						
							|  |  |  | 							`chunks:${selectedChunksKey} key:${cacheGroup.key}`; | 
					
						
							|  |  |  | 						// Add module to maps
 | 
					
						
							|  |  |  | 						let info = chunksInfoMap.get(key); | 
					
						
							|  |  |  | 						if (info === undefined) { | 
					
						
							|  |  |  | 							chunksInfoMap.set( | 
					
						
							|  |  |  | 								key, | 
					
						
							|  |  |  | 								(info = { | 
					
						
							| 
									
										
										
										
											2018-08-28 17:50:33 +08:00
										 |  |  | 									modules: new SortableSet( | 
					
						
							|  |  |  | 										undefined, | 
					
						
							|  |  |  | 										compareModulesByIdentifier | 
					
						
							|  |  |  | 									), | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 									cacheGroup, | 
					
						
							|  |  |  | 									name, | 
					
						
							|  |  |  | 									size: 0, | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 									chunks: new Set(), | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 									reuseableChunks: new Set(), | 
					
						
							|  |  |  | 									chunksKeys: new Set() | 
					
						
							|  |  |  | 								}) | 
					
						
							|  |  |  | 							); | 
					
						
							| 
									
										
										
										
											2018-07-05 20:39:07 +08:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 							if (info.cacheGroup !== cacheGroup) { | 
					
						
							|  |  |  | 								if (info.cacheGroup.priority < cacheGroup.priority) { | 
					
						
							|  |  |  | 									info.cacheGroup = cacheGroup; | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						info.modules.add(module); | 
					
						
							|  |  |  | 						info.size += module.size(); | 
					
						
							|  |  |  | 						if (!info.chunksKeys.has(selectedChunksKey)) { | 
					
						
							|  |  |  | 							info.chunksKeys.add(selectedChunksKey); | 
					
						
							|  |  |  | 							for (const chunk of selectedChunks) { | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 								info.chunks.add(chunk); | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					const context = { | 
					
						
							|  |  |  | 						moduleGraph, | 
					
						
							|  |  |  | 						chunkGraph | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					// Walk through all modules
 | 
					
						
							|  |  |  | 					for (const module of compilation.modules) { | 
					
						
							|  |  |  | 						// Get cache group
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						let cacheGroups = this.options.getCacheGroups(module, context); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 						if (!Array.isArray(cacheGroups) || cacheGroups.length === 0) { | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 							continue; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						// Prepare some values
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						const chunksKey = getKey( | 
					
						
							|  |  |  | 							chunkGraph.getModuleChunksIterable(module) | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 						let combs = combinationsCache.get(chunksKey); | 
					
						
							|  |  |  | 						if (combs === undefined) { | 
					
						
							|  |  |  | 							combs = getCombinations(chunksKey); | 
					
						
							|  |  |  | 							combinationsCache.set(chunksKey, combs); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						for (const cacheGroupSource of cacheGroups) { | 
					
						
							|  |  |  | 							const cacheGroup = { | 
					
						
							|  |  |  | 								key: cacheGroupSource.key, | 
					
						
							|  |  |  | 								priority: cacheGroupSource.priority || 0, | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 								chunksFilter: | 
					
						
							|  |  |  | 									cacheGroupSource.chunksFilter || this.options.chunksFilter, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								minSize: | 
					
						
							|  |  |  | 									cacheGroupSource.minSize !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.minSize | 
					
						
							| 
									
										
										
										
											2018-04-26 22:32:23 +08:00
										 |  |  | 										: cacheGroupSource.enforce | 
					
						
							|  |  |  | 											? 0 | 
					
						
							|  |  |  | 											: this.options.minSize, | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 								maxSize: | 
					
						
							|  |  |  | 									cacheGroupSource.maxSize !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.maxSize | 
					
						
							|  |  |  | 										: cacheGroupSource.enforce | 
					
						
							|  |  |  | 											? 0 | 
					
						
							|  |  |  | 											: this.options.maxSize, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								minChunks: | 
					
						
							|  |  |  | 									cacheGroupSource.minChunks !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.minChunks | 
					
						
							| 
									
										
										
										
											2018-04-26 22:32:23 +08:00
										 |  |  | 										: cacheGroupSource.enforce | 
					
						
							|  |  |  | 											? 1 | 
					
						
							|  |  |  | 											: this.options.minChunks, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								maxAsyncRequests: | 
					
						
							|  |  |  | 									cacheGroupSource.maxAsyncRequests !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.maxAsyncRequests | 
					
						
							|  |  |  | 										: cacheGroupSource.enforce | 
					
						
							|  |  |  | 											? Infinity | 
					
						
							|  |  |  | 											: this.options.maxAsyncRequests, | 
					
						
							|  |  |  | 								maxInitialRequests: | 
					
						
							|  |  |  | 									cacheGroupSource.maxInitialRequests !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.maxInitialRequests | 
					
						
							|  |  |  | 										: cacheGroupSource.enforce | 
					
						
							|  |  |  | 											? Infinity | 
					
						
							|  |  |  | 											: this.options.maxInitialRequests, | 
					
						
							|  |  |  | 								getName: | 
					
						
							|  |  |  | 									cacheGroupSource.getName !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.getName | 
					
						
							|  |  |  | 										: this.options.getName, | 
					
						
							| 
									
										
										
										
											2018-03-02 17:14:25 +08:00
										 |  |  | 								filename: | 
					
						
							|  |  |  | 									cacheGroupSource.filename !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.filename | 
					
						
							|  |  |  | 										: this.options.filename, | 
					
						
							| 
									
										
										
										
											2018-07-05 19:19:55 +08:00
										 |  |  | 								automaticNameDelimiter: | 
					
						
							|  |  |  | 									cacheGroupSource.automaticNameDelimiter !== undefined | 
					
						
							|  |  |  | 										? cacheGroupSource.automaticNameDelimiter | 
					
						
							|  |  |  | 										: this.options.automaticNameDelimiter, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								reuseExistingChunk: cacheGroupSource.reuseExistingChunk | 
					
						
							|  |  |  | 							}; | 
					
						
							|  |  |  | 							// For all combination of chunk selection
 | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 							for (const chunkCombination of combs) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								// Break if minimum number of chunks is not reached
 | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 								if (chunkCombination.size < cacheGroup.minChunks) continue; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								// Select chunks by configuration
 | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 								const { | 
					
						
							|  |  |  | 									chunks: selectedChunks, | 
					
						
							|  |  |  | 									key: selectedChunksKey | 
					
						
							|  |  |  | 								} = getSelectedChunks( | 
					
						
							|  |  |  | 									chunkCombination, | 
					
						
							| 
									
										
										
										
											2018-03-20 20:18:09 +08:00
										 |  |  | 									cacheGroup.chunksFilter | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								addModuleToChunksInfoMap( | 
					
						
							|  |  |  | 									cacheGroup, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									selectedChunks, | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 									selectedChunksKey, | 
					
						
							|  |  |  | 									module | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 					/** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string}>} */ | 
					
						
							|  |  |  | 					const maxSizeQueueMap = new Map(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					while (chunksInfoMap.size > 0) { | 
					
						
							|  |  |  | 						// Find best matching entry
 | 
					
						
							|  |  |  | 						let bestEntryKey; | 
					
						
							|  |  |  | 						let bestEntry; | 
					
						
							|  |  |  | 						for (const pair of chunksInfoMap) { | 
					
						
							|  |  |  | 							const key = pair[0]; | 
					
						
							|  |  |  | 							const info = pair[1]; | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							if (info.size >= info.cacheGroup.minSize) { | 
					
						
							|  |  |  | 								if (bestEntry === undefined) { | 
					
						
							|  |  |  | 									bestEntry = info; | 
					
						
							|  |  |  | 									bestEntryKey = key; | 
					
						
							|  |  |  | 								} else if (compareEntries(bestEntry, info) < 0) { | 
					
						
							|  |  |  | 									bestEntry = info; | 
					
						
							|  |  |  | 									bestEntryKey = key; | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						// No suitable item left
 | 
					
						
							|  |  |  | 						if (bestEntry === undefined) break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						const item = bestEntry; | 
					
						
							|  |  |  | 						chunksInfoMap.delete(bestEntryKey); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						let chunkName = item.name; | 
					
						
							|  |  |  | 						// Variable for the new chunk (lazy created)
 | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 						/** @type {Chunk} */ | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						let newChunk; | 
					
						
							|  |  |  | 						// When no chunk name, check if we can reuse a chunk instead of creating a new one
 | 
					
						
							|  |  |  | 						let isReused = false; | 
					
						
							|  |  |  | 						if (item.cacheGroup.reuseExistingChunk) { | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 							outer: for (const chunk of item.chunks) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 								if ( | 
					
						
							|  |  |  | 									chunkGraph.getNumberOfChunkModules(chunk) !== | 
					
						
							|  |  |  | 									item.modules.size | 
					
						
							|  |  |  | 								) | 
					
						
							|  |  |  | 									continue; | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 								if (chunkGraph.getNumberOfEntryModules(chunk) > 0) continue; | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 								for (const module of item.modules) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 									if (!chunkGraph.isModuleInChunk(module, chunk)) | 
					
						
							|  |  |  | 										continue outer; | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 								if (!newChunk || !newChunk.name) { | 
					
						
							|  |  |  | 									newChunk = chunk; | 
					
						
							|  |  |  | 								} else if ( | 
					
						
							|  |  |  | 									chunk.name && | 
					
						
							|  |  |  | 									chunk.name.length < newChunk.name.length | 
					
						
							|  |  |  | 								) { | 
					
						
							|  |  |  | 									newChunk = chunk; | 
					
						
							|  |  |  | 								} else if ( | 
					
						
							|  |  |  | 									chunk.name && | 
					
						
							|  |  |  | 									chunk.name.length === newChunk.name.length && | 
					
						
							|  |  |  | 									chunk.name < newChunk.name | 
					
						
							|  |  |  | 								) { | 
					
						
							|  |  |  | 									newChunk = chunk; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 								chunkName = undefined; | 
					
						
							|  |  |  | 								isReused = true; | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-07-10 04:48:12 +08:00
										 |  |  | 						// Check if maxRequests condition can be fulfilled
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-20 00:21:09 +08:00
										 |  |  | 						const usedChunks = Array.from(item.chunks).filter(chunk => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							// skip if we address ourself
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							return ( | 
					
						
							|  |  |  | 								(!chunkName || chunk.name !== chunkName) && chunk !== newChunk | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// Skip when no chunk selected
 | 
					
						
							|  |  |  | 						if (usedChunks.length === 0) continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						const chunkInLimit = usedChunks.filter(chunk => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							// respect max requests when not enforced
 | 
					
						
							|  |  |  | 							const maxRequests = chunk.isOnlyInitial() | 
					
						
							|  |  |  | 								? item.cacheGroup.maxInitialRequests | 
					
						
							|  |  |  | 								: chunk.canBeInitial() | 
					
						
							|  |  |  | 									? Math.min( | 
					
						
							|  |  |  | 											item.cacheGroup.maxInitialRequests, | 
					
						
							|  |  |  | 											item.cacheGroup.maxAsyncRequests | 
					
						
							| 
									
										
										
										
											2018-03-26 22:56:10 +08:00
										 |  |  | 									  ) | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									: item.cacheGroup.maxAsyncRequests; | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							return !isFinite(maxRequests) || getRequests(chunk) < maxRequests; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						if (chunkInLimit.length < usedChunks.length) { | 
					
						
							|  |  |  | 							for (const module of item.modules) { | 
					
						
							|  |  |  | 								addModuleToChunksInfoMap( | 
					
						
							|  |  |  | 									item.cacheGroup, | 
					
						
							|  |  |  | 									chunkInLimit, | 
					
						
							|  |  |  | 									getKey(chunkInLimit), | 
					
						
							|  |  |  | 									module | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							continue; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// Create the new chunk if not reusing one
 | 
					
						
							|  |  |  | 						if (!isReused) { | 
					
						
							|  |  |  | 							newChunk = compilation.addChunk(chunkName); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						// Walk through all chunks
 | 
					
						
							|  |  |  | 						for (const chunk of usedChunks) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							// Add graph connections for splitted chunk
 | 
					
						
							|  |  |  | 							chunk.split(newChunk); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						// Add a note to the chunk
 | 
					
						
							|  |  |  | 						newChunk.chunkReason = isReused | 
					
						
							|  |  |  | 							? "reused as split chunk" | 
					
						
							|  |  |  | 							: "split chunk"; | 
					
						
							|  |  |  | 						if (item.cacheGroup.key) { | 
					
						
							|  |  |  | 							newChunk.chunkReason += ` (cache group: ${item.cacheGroup.key})`; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (chunkName) { | 
					
						
							|  |  |  | 							newChunk.chunkReason += ` (name: ${chunkName})`; | 
					
						
							|  |  |  | 							// If the chosen name is already an entry point we remove the entry point
 | 
					
						
							|  |  |  | 							const entrypoint = compilation.entrypoints.get(chunkName); | 
					
						
							|  |  |  | 							if (entrypoint) { | 
					
						
							|  |  |  | 								compilation.entrypoints.delete(chunkName); | 
					
						
							|  |  |  | 								entrypoint.remove(); | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 								chunkGraph.disconnectEntries(newChunk); | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (item.cacheGroup.filename) { | 
					
						
							|  |  |  | 							if (!newChunk.isOnlyInitial()) { | 
					
						
							|  |  |  | 								throw new Error( | 
					
						
							|  |  |  | 									"SplitChunksPlugin: You are trying to set a filename for a chunk which is (also) loaded on demand. " + | 
					
						
							|  |  |  | 										"The runtime can only handle loading of chunks which match the chunkFilename schema. " + | 
					
						
							|  |  |  | 										"Using a custom filename would fail at runtime. " + | 
					
						
							|  |  |  | 										`(cache group: ${item.cacheGroup.key})` | 
					
						
							|  |  |  | 								); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 							newChunk.filenameTemplate = item.cacheGroup.filename; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						if (!isReused) { | 
					
						
							|  |  |  | 							// Add all modules to the new chunk
 | 
					
						
							|  |  |  | 							for (const module of item.modules) { | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 								if (!module.chunkCondition(newChunk, compilation)) continue; | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 								// Add module to new chunk
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 								chunkGraph.connectChunkAndModule(newChunk, module); | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 								// Remove module from used chunks
 | 
					
						
							|  |  |  | 								for (const chunk of usedChunks) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 									chunkGraph.disconnectChunkAndModule(chunk, module); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						} else { | 
					
						
							|  |  |  | 							// Remove all modules from used chunks
 | 
					
						
							|  |  |  | 							for (const module of item.modules) { | 
					
						
							|  |  |  | 								for (const chunk of usedChunks) { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 									chunkGraph.disconnectChunkAndModule(chunk, module); | 
					
						
							| 
									
										
										
										
											2018-03-02 17:14:25 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						if (item.cacheGroup.maxSize > 0) { | 
					
						
							|  |  |  | 							const oldMaxSizeSettings = maxSizeQueueMap.get(newChunk); | 
					
						
							|  |  |  | 							maxSizeQueueMap.set(newChunk, { | 
					
						
							|  |  |  | 								minSize: Math.max( | 
					
						
							|  |  |  | 									oldMaxSizeSettings ? oldMaxSizeSettings.minSize : 0, | 
					
						
							|  |  |  | 									item.cacheGroup.minSize | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 								maxSize: Math.min( | 
					
						
							|  |  |  | 									oldMaxSizeSettings ? oldMaxSizeSettings.maxSize : Infinity, | 
					
						
							|  |  |  | 									item.cacheGroup.maxSize | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 								automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter | 
					
						
							|  |  |  | 							}); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 						// remove all modules from other entries and update size
 | 
					
						
							|  |  |  | 						for (const [key, info] of chunksInfoMap) { | 
					
						
							|  |  |  | 							if (isOverlap(info.chunks, item.chunks)) { | 
					
						
							|  |  |  | 								const oldSize = info.modules.size; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								for (const module of item.modules) { | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 									info.modules.delete(module); | 
					
						
							| 
									
										
										
										
											2018-04-27 20:29:34 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 								if (info.modules.size === 0) { | 
					
						
							|  |  |  | 									chunksInfoMap.delete(key); | 
					
						
							|  |  |  | 									continue; | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-05-17 18:35:13 +08:00
										 |  |  | 								if (info.modules.size !== oldSize) { | 
					
						
							|  |  |  | 									info.size = getModulesSize(info.modules); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 									if (info.size < info.cacheGroup.minSize) { | 
					
						
							| 
									
										
										
										
											2018-02-16 16:12:01 +08:00
										 |  |  | 										chunksInfoMap.delete(key); | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// Make sure that maxSize is fulfilled
 | 
					
						
							| 
									
										
										
										
											2018-09-06 22:59:11 +08:00
										 |  |  | 					for (const chunk of Array.from(compilation.chunks)) { | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 						const { minSize, maxSize, automaticNameDelimiter } = | 
					
						
							|  |  |  | 							maxSizeQueueMap.get(chunk) || this.options.fallbackCacheGroup; | 
					
						
							|  |  |  | 						if (!maxSize) continue; | 
					
						
							|  |  |  | 						const results = deterministicGroupingForModules({ | 
					
						
							| 
									
										
										
										
											2018-11-23 15:49:35 +08:00
										 |  |  | 							maxSize: Math.max(minSize, maxSize), | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 							minSize, | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 							items: chunkGraph.getChunkModulesIterable(chunk), | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 							getKey(module) { | 
					
						
							|  |  |  | 								const ident = contextify( | 
					
						
							|  |  |  | 									compilation.options.context, | 
					
						
							|  |  |  | 									module.identifier() | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 								const name = module.nameForCondition | 
					
						
							|  |  |  | 									? contextify( | 
					
						
							|  |  |  | 											compilation.options.context, | 
					
						
							|  |  |  | 											module.nameForCondition() | 
					
						
							|  |  |  | 									  ) | 
					
						
							|  |  |  | 									: ident.replace(/^.*!|\?[^?!]*$/g, ""); | 
					
						
							|  |  |  | 								const fullKey = | 
					
						
							|  |  |  | 									name + automaticNameDelimiter + hashFilename(ident); | 
					
						
							|  |  |  | 								return fullKey.replace(/[\\/?]/g, "_"); | 
					
						
							|  |  |  | 							}, | 
					
						
							|  |  |  | 							getSize(module) { | 
					
						
							|  |  |  | 								return module.size(); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						results.sort((a, b) => { | 
					
						
							|  |  |  | 							if (a.key < b.key) return -1; | 
					
						
							|  |  |  | 							if (a.key > b.key) return 1; | 
					
						
							|  |  |  | 							return 0; | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						for (let i = 0; i < results.length; i++) { | 
					
						
							|  |  |  | 							const group = results[i]; | 
					
						
							|  |  |  | 							const key = this.options.hidePathInfo | 
					
						
							|  |  |  | 								? hashFilename(group.key) | 
					
						
							|  |  |  | 								: group.key; | 
					
						
							|  |  |  | 							let name = chunk.name | 
					
						
							|  |  |  | 								? chunk.name + automaticNameDelimiter + key | 
					
						
							|  |  |  | 								: null; | 
					
						
							|  |  |  | 							if (name && name.length > 100) { | 
					
						
							|  |  |  | 								name = | 
					
						
							|  |  |  | 									name.slice(0, 100) + | 
					
						
							|  |  |  | 									automaticNameDelimiter + | 
					
						
							|  |  |  | 									hashFilename(name); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							let newPart; | 
					
						
							|  |  |  | 							if (i !== results.length - 1) { | 
					
						
							|  |  |  | 								newPart = compilation.addChunk(name); | 
					
						
							|  |  |  | 								chunk.split(newPart); | 
					
						
							| 
									
										
										
										
											2018-07-10 16:24:22 +08:00
										 |  |  | 								newPart.chunkReason = chunk.chunkReason; | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 								// Add all modules to the new chunk
 | 
					
						
							|  |  |  | 								for (const module of group.items) { | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 									if (!module.chunkCondition(newPart, compilation)) continue; | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 									// Add module to new chunk
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 									chunkGraph.connectChunkAndModule(newPart, module); | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 									// Remove module from used chunks
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 									chunkGraph.disconnectChunkAndModule(chunk, module); | 
					
						
							| 
									
										
										
										
											2018-07-04 15:59:22 +08:00
										 |  |  | 								} | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								// change the chunk to be a part
 | 
					
						
							|  |  |  | 								newPart = chunk; | 
					
						
							|  |  |  | 								chunk.name = name; | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; |