Repository: webpack/webpack
Pull request #6353 (2018-01-22 11:17:33)

split Chunk.isInitial into isOnlyInitial and canBeInitial

<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->

**What kind of change does this PR introduce?**
bugfix
<!-- E.g. a bugfix, feature, refactoring, build related change, etc… -->

**Did you add tests for your changes?**
no and I feel bad about this
<!-- Note that we won't merge your changes if you don't add tests -->

**If relevant, link to documentation update:**
N/A
<!-- Link PR from webpack/webpack.js.org here, or N/A -->

**Summary**
split Chunk.isInitial into isOnlyInitial and canBeInitial
remove includeInitial argument of getChunk(Module)Maps

<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
<!-- Try to link to an open issue for more information. -->

**Does this PR introduce a breaking change?**
yes
<!-- If this PR introduces a breaking change, please describe the impact and a migration path for existing applications. -->

**Other information**



Patch:
diff --git a/lib/BannerPlugin.js b/lib/BannerPlugin.js
index 7b3b8f202..d16384f91 100644
--- a/lib/BannerPlugin.js
+++ b/lib/BannerPlugin.js
@@ -39,7 +39,7 @@ class BannerPlugin {
 		compiler.hooks.compilation.tap("BannerPlugin", (compilation) => {
 			compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", (chunks) => {
 				chunks.forEach((chunk) => {
-					if(options.entryOnly && !chunk.isInitial()) return;
+					if(options.entryOnly && !chunk.canBeInitial()) return;
 					chunk.files
 						.filter(ModuleFilenameHelpers.matchObject.bind(undefined, options))
 						.forEach((file) => {
diff --git a/lib/Chunk.js b/lib/Chunk.js
index f1afd78e3..14bdad062 100644
--- a/lib/Chunk.js
+++ b/lib/Chunk.js
@@ -69,11 +69,11 @@ class Chunk {
 	}
 
 	get initial() {
-		throw new Error("Chunk.initial was removed. Use isInitial()");
+		throw new Error("Chunk.initial was removed. Use canBeInitial/isOnlyInitial()");
 	}
 
 	set initial(data) {
-		throw new Error("Chunk.initial was removed. Use isInitial()");
+		throw new Error("Chunk.initial was removed. Use canBeInitial/isOnlyInitial()");
 	}
 
 	hasRuntime() {
@@ -84,14 +84,23 @@ class Chunk {
 		return false;
 	}
 
-	isInitial() {
+	canBeInitial() {
 		for(const chunkGroup of this._groups) {
-			// We only need to check the first one
-			return chunkGroup.isInitial();
+			if(chunkGroup.isInitial())
+				return true;
 		}
 		return false;
 	}
 
+	isOnlyInitial() {
+		if(this._groups.size <= 0) return false;
+		for(const chunkGroup of this._groups) {
+			if(!chunkGroup.isInitial())
+				return false;
+		}
+		return true;
+	}
+
 	hasEntryModule() {
 		return !!this.entryModule;
 	}
@@ -263,10 +272,10 @@ class Chunk {
 			}
 			return true;
 		};
-		if(this.isInitial() !== otherChunk.isInitial()) {
-			if(this.isInitial()) {
+		if(this.hasRuntime() !== otherChunk.hasRuntime()) {
+			if(this.hasRuntime()) {
 				return isAvailable(this, otherChunk);
-			} else if(otherChunk.isInitial()) {
+			} else if(otherChunk.hasRuntime()) {
 				return isAvailable(otherChunk, this);
 			} else {
 				return false;
@@ -279,7 +288,7 @@ class Chunk {
 
 	addMultiplierAndOverhead(size, options) {
 		const overhead = typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
-		const multiplicator = this.isInitial() ? (options.entryChunkMultiplicator || 10) : 1;
+		const multiplicator = this.canBeInitial() ? (options.entryChunkMultiplicator || 10) : 1;
 
 		return size * multiplicator + overhead;
 	}
@@ -317,22 +326,33 @@ class Chunk {
 		this.sortModules();
 	}
 
-	getChunkMaps(includeInitial, realHash) {
-		const chunkHashMap = Object.create(null);
-		const chunkNameMap = Object.create(null);
-
+	getAllAsyncChunks() {
+		const initialChunks = new Set();
 		const queue = new Set(this.groupsIterable);
 		const chunks = new Set();
 
 		for(const chunkGroup of queue) {
-			if(includeInitial || !chunkGroup.isInitial())
-				for(const chunk of chunkGroup.chunks)
+			for(const chunk of chunkGroup.chunks)
+				initialChunks.add(chunk);
+		}
+
+		for(const chunkGroup of queue) {
+			for(const chunk of chunkGroup.chunks) {
+				if(!initialChunks.has(chunk))
 					chunks.add(chunk);
+			}
 			for(const child of chunkGroup.childrenIterable)
 				queue.add(child);
 		}
 
-		for(const chunk of chunks) {
+		return chunks;
+	}
+
+	getChunkMaps(realHash) {
+		const chunkHashMap = Object.create(null);
+		const chunkNameMap = Object.create(null);
+
+		for(const chunk of this.getAllAsyncChunks()) {
 			chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
 			if(chunk.name)
 				chunkNameMap[chunk.id] = chunk.name;
@@ -344,22 +364,11 @@ class Chunk {
 		};
 	}
 
-	getChunkModuleMaps(includeInitial, filterFn) {
+	getChunkModuleMaps(filterFn) {
 		const chunkModuleIdMap = Object.create(null);
 		const chunkModuleHashMap = Object.create(null);
 
-		const queue = new Set(this.groupsIterable);
-		const chunks = new Set();
-
-		for(const chunkGroup of queue) {
-			if(includeInitial || !chunkGroup.isInitial())
-				for(const chunk of chunkGroup.chunks)
-					chunks.add(chunk);
-			for(const child of chunkGroup.childrenIterable)
-				queue.add(child);
-		}
-
-		for(const chunk of chunks) {
+		for(const chunk of this.getAllAsyncChunks()) {
 			let array;
 			for(const module of chunk.modulesIterable) {
 				if(filterFn(module)) {
diff --git a/lib/FlagInitialModulesAsUsedPlugin.js b/lib/FlagInitialModulesAsUsedPlugin.js
index ac45dd54e..f17020566 100644
--- a/lib/FlagInitialModulesAsUsedPlugin.js
+++ b/lib/FlagInitialModulesAsUsedPlugin.js
@@ -13,7 +13,7 @@ class FlagInitialModulesAsUsedPlugin {
 		compiler.hooks.compilation.tap("FlagInitialModulesAsUsedPlugin", (compilation) => {
 			compilation.hooks.afterOptimizeChunks.tap("FlagInitialModulesAsUsedPlugin", (chunks) => {
 				chunks.forEach((chunk) => {
-					if(!chunk.isInitial()) {
+					if(!chunk.isOnlyInitial()) {
 						return;
 					}
 					for(const module of chunk.modulesIterable) {
diff --git a/lib/LibManifestPlugin.js b/lib/LibManifestPlugin.js
index 6acded676..bbbecbf3b 100644
--- a/lib/LibManifestPlugin.js
+++ b/lib/LibManifestPlugin.js
@@ -15,7 +15,7 @@ class LibManifestPlugin {
 	apply(compiler) {
 		compiler.hooks.emit.tapAsync("LibManifestPlugin", (compilation, callback) => {
 			asyncLib.forEach(compilation.chunks, (chunk, callback) => {
-				if(!chunk.isInitial()) {
+				if(!chunk.isOnlyInitial()) {
 					callback();
 					return;
 				}
diff --git a/lib/Stats.js b/lib/Stats.js
index 3129c7da1..0e723d646 100644
--- a/lib/Stats.js
+++ b/lib/Stats.js
@@ -193,7 +193,7 @@ class Stats {
 					message: e
 				};
 			if(e.chunk) {
-				text += `chunk ${e.chunk.name || e.chunk.id}${e.chunk.hasRuntime() ? " [entry]" : e.chunk.isInitial() ? " [initial]" : ""}\n`;
+				text += `chunk ${e.chunk.name || e.chunk.id}${e.chunk.hasRuntime() ? " [entry]" : e.chunk.canBeInitial() ? " [initial]" : ""}\n`;
 			}
 			if(e.file) {
 				text += `${e.file}\n`;
@@ -431,7 +431,7 @@ class Stats {
 				const obj = {
 					id: chunk.id,
 					rendered: chunk.rendered,
-					initial: chunk.isInitial(),
+					initial: chunk.canBeInitial(),
 					entry: chunk.hasRuntime(),
 					recorded: chunk.recorded,
 					reason: chunk.chunkReason,
diff --git a/lib/TemplatedPathPlugin.js b/lib/TemplatedPathPlugin.js
index b2b7c77b5..82e0f57ba 100644
--- a/lib/TemplatedPathPlugin.js
+++ b/lib/TemplatedPathPlugin.js
@@ -104,9 +104,9 @@ class TemplatedPathPlugin {
 				const outputOptions = mainTemplate.outputOptions;
 				const chunkFilename = outputOptions.chunkFilename || outputOptions.filename;
 				if(REGEXP_CHUNKHASH_FOR_TEST.test(chunkFilename))
-					hash.update(JSON.stringify(chunk.getChunkMaps(false, true).hash));
+					hash.update(JSON.stringify(chunk.getChunkMaps(true).hash));
 				if(REGEXP_NAME_FOR_TEST.test(chunkFilename))
-					hash.update(JSON.stringify(chunk.getChunkMaps(false, true).name));
+					hash.update(JSON.stringify(chunk.getChunkMaps(true).name));
 			});
 		});
 	}
diff --git a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js
index cf61eda96..2e37c0d7b 100644
--- a/lib/node/ReadFileCompileWasmMainTemplatePlugin.js
+++ b/lib/node/ReadFileCompileWasmMainTemplatePlugin.js
@@ -19,7 +19,7 @@ class ReadFileCompileWasmMainTemplatePlugin {
 		});
 		mainTemplate.hooks.requireEnsure.tap("ReadFileCompileWasmMainTemplatePlugin", (source, chunk, hash) => {
 			const webassemblyModuleFilename = mainTemplate.outputOptions.webassemblyModuleFilename;
-			const chunkModuleMaps = chunk.getChunkModuleMaps(false, m => m.type.startsWith("webassembly"));
+			const chunkModuleMaps = chunk.getChunkModuleMaps(m => m.type.startsWith("webassembly"));
 			if(Object.keys(chunkModuleMaps.id).length === 0) return source;
 			const wasmModuleSrcPath = mainTemplate.getAssetPath(JSON.stringify(webassemblyModuleFilename), {
 				hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,
diff --git a/lib/optimize/AggressiveMergingPlugin.js b/lib/optimize/AggressiveMergingPlugin.js
index 12604a453..2af39f25d 100644
--- a/lib/optimize/AggressiveMergingPlugin.js
+++ b/lib/optimize/AggressiveMergingPlugin.js
@@ -20,10 +20,10 @@ class AggressiveMergingPlugin {
 			compilation.hooks.optimizeChunksAdvanced.tap("AggressiveMergingPlugin", (chunks) => {
 				let combinations = [];
 				chunks.forEach((a, idx) => {
-					if(a.isInitial()) return;
+					if(a.canBeInitial()) return;
 					for(let i = 0; i < idx; i++) {
 						const b = chunks[i];
-						if(b.isInitial()) continue;
+						if(b.canBeInitial()) continue;
 						combinations.push({
 							a,
 							b,
diff --git a/lib/optimize/MergeDuplicateChunksPlugin.js b/lib/optimize/MergeDuplicateChunksPlugin.js
index 189692320..4285b2593 100644
--- a/lib/optimize/MergeDuplicateChunksPlugin.js
+++ b/lib/optimize/MergeDuplicateChunksPlugin.js
@@ -47,7 +47,7 @@ class MergeDuplicateChunksPlugin {
 					// when we found duplicates
 					if(possibleDuplicates !== undefined && possibleDuplicates.size > 0) {
 						for(const otherChunk of possibleDuplicates) {
-							if(otherChunk.isInitial() !== chunk.isInitial()) continue;
+							if(otherChunk.hasRuntime() !== chunk.hasRuntime()) continue;
 							// merge them
 							if(chunk.integrate(otherChunk, "duplicate"))
 								chunks.splice(chunks.indexOf(otherChunk), 1);
diff --git a/lib/optimize/OccurrenceOrderPlugin.js b/lib/optimize/OccurrenceOrderPlugin.js
index 6c59d3b70..baa8c9b3a 100644
--- a/lib/optimize/OccurrenceOrderPlugin.js
+++ b/lib/optimize/OccurrenceOrderPlugin.js
@@ -24,7 +24,7 @@ class OccurrenceOrderPlugin {
 					let initial = 0;
 					let entry = 0;
 					m.forEachChunk(c => {
-						if(c.isInitial()) initial++;
+						if(c.canBeInitial()) initial++;
 						if(c.entryModule === m) entry++;
 					});
 					initialChunkChunkMap.set(m, initial);
diff --git a/lib/optimize/SplitChunksPlugin.js b/lib/optimize/SplitChunksPlugin.js
index fc36dfa31..d93f5ba1d 100644
--- a/lib/optimize/SplitChunksPlugin.js
+++ b/lib/optimize/SplitChunksPlugin.js
@@ -213,8 +213,8 @@ module.exports = class SplitChunksPlugin {
 							reuseExistingChunk: cacheGroupSource.reuseExistingChunk
 						};
 						// Select chunks by configuration
-						const selectedChunks = cacheGroup.chunks === "initial" ? chunks.filter(chunk => chunk.isInitial()) :
-							cacheGroup.chunks === "async" ? chunks.filter(chunk => !chunk.isInitial()) :
+						const selectedChunks = cacheGroup.chunks === "initial" ? chunks.filter(chunk => chunk.canBeInitial()) :
+							cacheGroup.chunks === "async" ? chunks.filter(chunk => !chunk.canBeInitial()) :
 							chunks;
 						// Get indices of chunks in which this module occurs
 						const chunkIndices = selectedChunks.map(chunk => indexMap.get(chunk));
@@ -304,8 +304,8 @@ module.exports = class SplitChunksPlugin {
 						// skip if we address ourself
 						if(chunk.name === chunkName || chunk === newChunk) continue;
 						// respect max requests when not enforced
-						const maxRequests = chunk.isInitial() ?
-							item.cacheGroup.maxInitialRequests :
+						const maxRequests = chunk.isOnlyInitial() ? item.cacheGroup.maxInitialRequests :
+							chunk.canBeInitial() ? Math.min(item.cacheGroup.maxInitialRequests, item.cacheGroup.maxAsyncRequests) :
 							item.cacheGroup.maxAsyncRequests;
 						if(isFinite(maxRequests) && getRequests(chunk) >= maxRequests) continue;
 						if(newChunk === undefined) {
diff --git a/lib/performance/SizeLimitsPlugin.js b/lib/performance/SizeLimitsPlugin.js
index a47f87a08..0f1c72cc1 100644
--- a/lib/performance/SizeLimitsPlugin.js
+++ b/lib/performance/SizeLimitsPlugin.js
@@ -84,7 +84,7 @@ module.exports = class SizeLimitsPlugin {
 				}
 
 				if(warnings.length > 0) {
-					const hasAsyncChunks = compilation.chunks.filter(chunk => !chunk.isInitial()).length > 0;
+					const hasAsyncChunks = compilation.chunks.filter(chunk => !chunk.canBeInitial()).length > 0;
 
 					if(!hasAsyncChunks) {
 						warnings.push(new NoAsyncChunksWarning());
diff --git a/lib/wasm/WasmModuleTemplatePlugin.js b/lib/wasm/WasmModuleTemplatePlugin.js
index 490446543..88800ccbf 100644
--- a/lib/wasm/WasmModuleTemplatePlugin.js
+++ b/lib/wasm/WasmModuleTemplatePlugin.js
@@ -13,7 +13,7 @@ class WasmModuleTemplatePlugin {
 			chunk
 		}) => {
 			if(module.type && module.type.startsWith("webassembly")) {
-				if(chunk.isInitial())
+				if(chunk.canBeInitial())
 					throw new Error("Sync WebAsssmbly compilation is not yet implemented");
 				const generateExports = () => {
 					if(Array.isArray(module.buildMeta.providedExports) && Array.isArray(module.usedExports)) {
diff --git a/lib/web/FetchCompileWasmMainTemplatePlugin.js b/lib/web/FetchCompileWasmMainTemplatePlugin.js
index 57a6abe30..548b5b9cc 100644
--- a/lib/web/FetchCompileWasmMainTemplatePlugin.js
+++ b/lib/web/FetchCompileWasmMainTemplatePlugin.js
@@ -21,7 +21,7 @@ class FetchCompileWasmMainTemplatePlugin {
 		});
 		mainTemplate.hooks.requireEnsure.tap("FetchCompileWasmMainTemplatePlugin", (source, chunk, hash) => {
 			const webassemblyModuleFilename = mainTemplate.outputOptions.webassemblyModuleFilename;
-			const chunkModuleMaps = chunk.getChunkModuleMaps(false, m => m.type.startsWith("webassembly"));
+			const chunkModuleMaps = chunk.getChunkModuleMaps(m => m.type.startsWith("webassembly"));
 			if(Object.keys(chunkModuleMaps.id).length === 0) return source;
 			const wasmModuleSrcPath = mainTemplate.getAssetPath(JSON.stringify(webassemblyModuleFilename), {
 				hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`,


Test patch:
diff --git a/test/Chunk.unittest.js b/test/Chunk.unittest.js
index 779b32546..8b9d8ca52 100644
--- a/test/Chunk.unittest.js
+++ b/test/Chunk.unittest.js
@@ -14,7 +14,7 @@ describe("Chunk", () => {
 
 	it("returns a string with modules information", () => should(ChunkInstance.toString()).be.exactly("Chunk[]"));
 
-	it("should not be the initial instance", () => should(ChunkInstance.isInitial()).be.false());
+	it("should not be the initial instance", () => should(ChunkInstance.canBeInitial()).be.false());
 
 	describe("entry", () => {
 		it("returns an error if get entry", () =>
@@ -32,12 +32,12 @@ describe("Chunk", () => {
 		it("returns an error if get initial", () =>
 			should(() => {
 				ChunkInstance.initial;
-			}).throw("Chunk.initial was removed. Use isInitial()"));
+			}).throw("Chunk.initial was removed. Use canBeInitial/isOnlyInitial()"));
 
 		it("returns an error if set an initial", () =>
 			should(() => {
 				ChunkInstance.initial = 10;
-			}).throw("Chunk.initial was removed. Use isInitial()"));
+			}).throw("Chunk.initial was removed. Use canBeInitial/isOnlyInitial()"));
 	});
 
 	describe("hasRuntime", () => {
diff --git a/test/statsCases/async-commons-chunk-auto/expected.txt b/test/statsCases/async-commons-chunk-auto/expected.txt
index 24ed6ec4e..03425701e 100644
--- a/test/statsCases/async-commons-chunk-auto/expected.txt
+++ b/test/statsCases/async-commons-chunk-auto/expected.txt
@@ -252,74 +252,70 @@ Child multiple-vendors:
         [6] ./c.js 72 bytes {6} {11} [built]
 Child all:
     Entrypoint main = all/main.js
-    Entrypoint a = all/vendors~a~async-a~async-b~async-c~b~c.js all/vendors~a~async-a~async-b~b.js all/a.js
-    Entrypoint b = all/vendors~a~async-a~async-b~async-c~b~c.js all/vendors~a~async-a~async-b~b.js all/b.js
+    Entrypoint a = all/vendors~a~async-a~async-b~async-c~b~c.js all/a~async-a~async-b~b.js all/a.js
+    Entrypoint b = all/vendors~a~async-a~async-b~async-c~b~c.js all/a~async-a~async-b~b.js all/b.js
     Entrypoint c = all/vendors~a~async-a~async-b~async-c~b~c.js all/vendors~async-c~c.js all/c.js
-    chunk    {0} all/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{10}> ={9}= ={13}= ={2}= ={12}= ={11}= ={1}= ={4}= ={8}= ={3}= ={7}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
+    chunk    {0} all/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={8}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={7}= ={6}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
         > ./c c
         > ./b b
         > ./a a
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
-        [1] ./node_modules/x.js 20 bytes {0} {4} [built]
-    chunk    {1} all/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{11}> <{3}> <{4}> <{6}> <{10}> ={5}= ={0}= ={9}= ={4}= ={8}= ={2}= ={3}= ={7}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
+        [1] ./node_modules/x.js 20 bytes {0} {3} [built]
+    chunk    {1} all/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{5}> <{9}> ={4}= ={0}= ={8}= ={3}= ={7}= ={2}= ={6}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
         > ./g [] 6:0-47
         > ./g [] 6:0-47
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-    chunk    {2} all/vendors~a~async-a~async-b~b.js (vendors~a~async-a~async-b~b) 20 bytes <{10}> ={0}= ={12}= ={11}= ={1}= ={3}= ={7}= ={4}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+    chunk    {2} all/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={6}= ={3}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
         > ./b b
         > ./a a
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
-        [3] ./node_modules/y.js 20 bytes {2} {3} [built]
-    chunk    {3} all/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{10}> ={0}= ={2}= ={1}= ={7}= ={4}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~b)
-        > ./b [8] ./index.js 2:0-47
-        > ./a [8] ./index.js 1:0-47
-        [3] ./node_modules/y.js 20 bytes {2} {3} [built]
-    chunk    {4} all/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{10}> ={0}= ={9}= ={1}= ={8}= ={2}= ={3}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
+        [3] ./node_modules/y.js 20 bytes {2} [built]
+    chunk    {3} all/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={8}= ={1}= ={7}= ={2}= ={5}= >{1}< >{4}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
         > ./c [8] ./index.js 3:0-47
         > ./a [8] ./index.js 1:0-47
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [1] ./node_modules/x.js 20 bytes {0} {4} [built]
-    chunk    {5} all/async-g.js (async-g) 34 bytes <{0}> <{2}> <{11}> <{3}> <{4}> <{6}> ={1}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [1] ./node_modules/x.js 20 bytes {0} {3} [built]
+    chunk    {4} all/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{5}> ={1}= [rendered]
         > ./g [] 6:0-47
         > ./g [] 6:0-47
-        [9] ./g.js 34 bytes {5} [built]
-    chunk    {6} all/async-a.js (async-a) 156 bytes <{10}> ={0}= ={2}= ={3}= ={4}= >{1}< >{5}< [rendered]
+        [9] ./g.js 34 bytes {4} [built]
+    chunk    {5} all/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{4}< [rendered]
         > ./a [8] ./index.js 1:0-47
-        [6] ./a.js + 1 modules 156 bytes {6} {11} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {7} all/async-b.js (async-b) 92 bytes <{10}> ={0}= ={2}= ={1}= ={3}= [rendered]
+    chunk    {6} all/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
         > ./b [8] ./index.js 2:0-47
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [4] ./b.js 72 bytes {7} {12} [built]
-    chunk    {8} all/async-c.js (async-c) 72 bytes <{10}> ={0}= ={9}= ={1}= ={4}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk    {7} all/async-c.js (async-c) 72 bytes <{9}> ={0}= ={8}= ={1}= ={3}= [rendered]
         > ./c [8] ./index.js 3:0-47
-        [5] ./c.js 72 bytes {8} {13} [built]
-    chunk    {9} all/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{10}> ={0}= ={13}= ={1}= ={4}= ={8}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
+        [5] ./c.js 72 bytes {7} {12} [built]
+    chunk    {8} all/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={7}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
         > ./c c
         > ./c [8] ./index.js 3:0-47
-        [7] ./node_modules/z.js 20 bytes {9} [built]
-    chunk   {10} all/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{3}< >{7}< >{4}< >{6}< >{9}< >{8}< [entry] [rendered]
+        [7] ./node_modules/z.js 20 bytes {8} [built]
+    chunk    {9} all/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{6}< >{3}< >{5}< >{8}< >{7}< [entry] [rendered]
         > ./ main
-        [8] ./index.js 147 bytes {10} [built]
-    chunk   {11} all/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{5}< [entry] [rendered]
+        [8] ./index.js 147 bytes {9} [built]
+    chunk   {10} all/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{4}< [entry] [rendered]
         > ./a a
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [6] ./a.js + 1 modules 156 bytes {6} {11} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk   {12} all/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
+    chunk   {11} all/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
         > ./b b
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-        [4] ./b.js 72 bytes {7} {12} [built]
-    chunk   {13} all/c.js (c) 112 bytes ={0}= ={9}= [entry] [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk   {12} all/c.js (c) 112 bytes ={0}= ={8}= [entry] [rendered]
         > ./c c
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-        [5] ./c.js 72 bytes {8} {13} [built]
\ No newline at end of file
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+        [5] ./c.js 72 bytes {7} {12} [built]
\ No newline at end of file
diff --git a/test/statsCases/limit-chunk-count-plugin/expected.txt b/test/statsCases/limit-chunk-count-plugin/expected.txt
index 46ca906d8..f6fb9afc9 100644
--- a/test/statsCases/limit-chunk-count-plugin/expected.txt
+++ b/test/statsCases/limit-chunk-count-plugin/expected.txt
@@ -3,7 +3,7 @@ Child 1 chunks:
     Hash: 1c28a2310b8d6ad1d2ea
     Time: Xms
         Asset      Size  Chunks             Chunk Names
-    bundle.js  7.92 KiB       0  [emitted]  main
+    bundle.js  5.52 KiB       0  [emitted]  main
     Entrypoint main = bundle.js
     chunk    {0} bundle.js (main) 191 bytes <{0}> >{0}< [entry] [rendered]
         [0] ./index.js 73 bytes {0} [built]
diff --git a/test/statsCases/split-chunks/expected.txt b/test/statsCases/split-chunks/expected.txt
index 4885bcc35..8c8767f4b 100644
--- a/test/statsCases/split-chunks/expected.txt
+++ b/test/statsCases/split-chunks/expected.txt
@@ -69,77 +69,73 @@ Child default:
         [6] ./c.js 72 bytes {7} {12} [built]
 Child all-chunks:
     Entrypoint main = default/main.js
-    Entrypoint a = default/vendors~a~async-a~async-b~async-c~b~c.js default/vendors~a~async-a~async-b~b.js default/a.js
-    Entrypoint b = default/vendors~a~async-a~async-b~async-c~b~c.js default/vendors~a~async-a~async-b~b.js default/b.js
+    Entrypoint a = default/vendors~a~async-a~async-b~async-c~b~c.js default/a~async-a~async-b~b.js default/a.js
+    Entrypoint b = default/vendors~a~async-a~async-b~async-c~b~c.js default/a~async-a~async-b~b.js default/b.js
     Entrypoint c = default/vendors~a~async-a~async-b~async-c~b~c.js default/vendors~async-c~c.js default/c.js
-    chunk    {0} default/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{10}> ={9}= ={13}= ={2}= ={12}= ={11}= ={1}= ={4}= ={8}= ={3}= ={7}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
+    chunk    {0} default/vendors~a~async-a~async-b~async-c~b~c.js (vendors~a~async-a~async-b~async-c~b~c) 20 bytes <{9}> ={8}= ={12}= ={2}= ={11}= ={10}= ={1}= ={3}= ={7}= ={6}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~async-c~b~c)
         > ./c c
         > ./b b
         > ./a a
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
-        [1] ./node_modules/x.js 20 bytes {0} {4} [built]
-    chunk    {1} default/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{11}> <{3}> <{4}> <{6}> <{10}> ={5}= ={0}= ={9}= ={4}= ={8}= ={2}= ={3}= ={7}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
+        [1] ./node_modules/x.js 20 bytes {0} {3} [built]
+    chunk    {1} default/async-b~async-c~async-g~b~c.js (async-b~async-c~async-g~b~c) 20 bytes <{0}> <{2}> <{10}> <{3}> <{5}> <{9}> ={4}= ={0}= ={8}= ={3}= ={7}= ={2}= ={6}= [rendered] split chunk (cache group: default) (name: async-b~async-c~async-g~b~c)
         > ./g [] 6:0-47
         > ./g [] 6:0-47
         > ./c [8] ./index.js 3:0-47
         > ./b [8] ./index.js 2:0-47
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-    chunk    {2} default/vendors~a~async-a~async-b~b.js (vendors~a~async-a~async-b~b) 20 bytes <{10}> ={0}= ={12}= ={11}= ={1}= ={3}= ={7}= ={4}= ={6}= >{1}< >{5}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+    chunk    {2} default/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{9}> ={0}= ={11}= ={10}= ={1}= ={6}= ={3}= ={5}= >{1}< >{4}< [initial] [rendered] split chunk (cache group: vendors) (name: vendors~a~async-a~async-b~b)
         > ./b b
         > ./a a
         > ./b [8] ./index.js 2:0-47
         > ./a [8] ./index.js 1:0-47
-        [3] ./node_modules/y.js 20 bytes {2} {3} [built]
-    chunk    {3} default/a~async-a~async-b~b.js (a~async-a~async-b~b) 20 bytes <{10}> ={0}= ={2}= ={1}= ={7}= ={4}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~b)
-        > ./b [8] ./index.js 2:0-47
-        > ./a [8] ./index.js 1:0-47
-        [3] ./node_modules/y.js 20 bytes {2} {3} [built]
-    chunk    {4} default/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{10}> ={0}= ={9}= ={1}= ={8}= ={2}= ={3}= ={6}= >{1}< >{5}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
+        [3] ./node_modules/y.js 20 bytes {2} [built]
+    chunk    {3} default/a~async-a~async-b~async-c~b~c.js (a~async-a~async-b~async-c~b~c) 40 bytes <{9}> ={0}= ={8}= ={1}= ={7}= ={2}= ={5}= >{1}< >{4}< [rendered] split chunk (cache group: default) (name: a~async-a~async-b~async-c~b~c)
         > ./c [8] ./index.js 3:0-47
         > ./a [8] ./index.js 1:0-47
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [1] ./node_modules/x.js 20 bytes {0} {4} [built]
-    chunk    {5} default/async-g.js (async-g) 34 bytes <{0}> <{2}> <{11}> <{3}> <{4}> <{6}> ={1}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [1] ./node_modules/x.js 20 bytes {0} {3} [built]
+    chunk    {4} default/async-g.js (async-g) 34 bytes <{0}> <{2}> <{10}> <{3}> <{5}> ={1}= [rendered]
         > ./g [] 6:0-47
         > ./g [] 6:0-47
-        [9] ./g.js 34 bytes {5} [built]
-    chunk    {6} default/async-a.js (async-a) 156 bytes <{10}> ={0}= ={2}= ={3}= ={4}= >{1}< >{5}< [rendered]
+        [9] ./g.js 34 bytes {4} [built]
+    chunk    {5} default/async-a.js (async-a) 156 bytes <{9}> ={0}= ={2}= ={3}= >{1}< >{4}< [rendered]
         > ./a [8] ./index.js 1:0-47
-        [6] ./a.js + 1 modules 156 bytes {6} {11} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk    {7} default/async-b.js (async-b) 92 bytes <{10}> ={0}= ={2}= ={1}= ={3}= [rendered]
+    chunk    {6} default/async-b.js (async-b) 92 bytes <{9}> ={0}= ={2}= ={1}= [rendered]
         > ./b [8] ./index.js 2:0-47
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [4] ./b.js 72 bytes {7} {12} [built]
-    chunk    {8} default/async-c.js (async-c) 72 bytes <{10}> ={0}= ={9}= ={1}= ={4}= [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk    {7} default/async-c.js (async-c) 72 bytes <{9}> ={0}= ={8}= ={1}= ={3}= [rendered]
         > ./c [8] ./index.js 3:0-47
-        [5] ./c.js 72 bytes {8} {13} [built]
-    chunk    {9} default/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{10}> ={0}= ={13}= ={1}= ={4}= ={8}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
+        [5] ./c.js 72 bytes {7} {12} [built]
+    chunk    {8} default/vendors~async-c~c.js (vendors~async-c~c) 20 bytes <{9}> ={0}= ={12}= ={1}= ={3}= ={7}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~async-c~c)
         > ./c c
         > ./c [8] ./index.js 3:0-47
-        [7] ./node_modules/z.js 20 bytes {9} [built]
-    chunk   {10} default/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{3}< >{7}< >{4}< >{6}< >{9}< >{8}< [entry] [rendered]
+        [7] ./node_modules/z.js 20 bytes {8} [built]
+    chunk    {9} default/main.js (main) 147 bytes >{0}< >{2}< >{1}< >{6}< >{3}< >{5}< >{8}< >{7}< [entry] [rendered]
         > ./ main
-        [8] ./index.js 147 bytes {10} [built]
-    chunk   {11} default/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{5}< [entry] [rendered]
+        [8] ./index.js 147 bytes {9} [built]
+    chunk   {10} default/a.js (a) 176 bytes ={0}= ={2}= >{1}< >{4}< [entry] [rendered]
         > ./a a
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [6] ./a.js + 1 modules 156 bytes {6} {11} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [6] ./a.js + 1 modules 156 bytes {5} {10} [built]
             | ./a.js 121 bytes [built]
             | ./e.js 20 bytes [built]
-    chunk   {12} default/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
+    chunk   {11} default/b.js (b) 112 bytes ={0}= ={2}= [entry] [rendered]
         > ./b b
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-        [4] ./b.js 72 bytes {7} {12} [built]
-    chunk   {13} default/c.js (c) 112 bytes ={0}= ={9}= [entry] [rendered]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+        [4] ./b.js 72 bytes {6} {11} [built]
+    chunk   {12} default/c.js (c) 112 bytes ={0}= ={8}= [entry] [rendered]
         > ./c c
-        [0] ./d.js 20 bytes {4} {7} {11} {12} {13} [built]
-        [2] ./f.js 20 bytes {1} {12} {13} [built]
-        [5] ./c.js 72 bytes {8} {13} [built]
+        [0] ./d.js 20 bytes {3} {6} {10} {11} {12} [built]
+        [2] ./f.js 20 bytes {1} {11} {12} [built]
+        [5] ./c.js 72 bytes {7} {12} [built]
 Child manual:
     Entrypoint main = default/main.js
     Entrypoint a = default/vendors.js default/a.js