mirror of https://github.com/webpack/webpack.git
				
				
				
			upgrade filename runtime module to full hash module when referencing a full hash chunk
This commit is contained in:
		
							parent
							
								
									179d2e00fe
								
							
						
					
					
						commit
						b16568a253
					
				|  | @ -205,6 +205,8 @@ class ChunkGraphChunk { | |||
| 		this.runtimeModules = new SortableSet(); | ||||
| 		/** @type {Set<RuntimeModule> | undefined} */ | ||||
| 		this.fullHashModules = undefined; | ||||
| 		/** @type {Set<RuntimeModule> | undefined} */ | ||||
| 		this.dependentHashModules = undefined; | ||||
| 		/** @type {Set<string> | undefined} */ | ||||
| 		this.runtimeRequirements = undefined; | ||||
| 		/** @type {Set<string>} */ | ||||
|  | @ -389,6 +391,20 @@ class ChunkGraph { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk | ||||
| 	 * @param {Iterable<RuntimeModule>} modules the modules that require a full hash | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	attachDependentHashModules(chunk, modules) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		if (cgc.dependentHashModules === undefined) | ||||
| 			cgc.dependentHashModules = new Set(); | ||||
| 		for (const module of modules) { | ||||
| 			cgc.dependentHashModules.add(module); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Module} oldModule the replaced module | ||||
| 	 * @param {Module} newModule the replacing module | ||||
|  | @ -444,6 +460,17 @@ class ChunkGraph { | |||
| 					cgc.fullHashModules.delete(/** @type {RuntimeModule} */ (oldModule)); | ||||
| 					cgc.fullHashModules.add(/** @type {RuntimeModule} */ (newModule)); | ||||
| 				} | ||||
| 				if ( | ||||
| 					cgc.dependentHashModules !== undefined && | ||||
| 					cgc.dependentHashModules.has(/** @type {RuntimeModule} */ (oldModule)) | ||||
| 				) { | ||||
| 					cgc.dependentHashModules.delete( | ||||
| 						/** @type {RuntimeModule} */ (oldModule) | ||||
| 					); | ||||
| 					cgc.dependentHashModules.add( | ||||
| 						/** @type {RuntimeModule} */ (newModule) | ||||
| 					); | ||||
| 				} | ||||
| 			} | ||||
| 			oldCgm.runtimeInChunks = undefined; | ||||
| 		} | ||||
|  | @ -529,13 +556,22 @@ class ChunkGraph { | |||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk | ||||
| 	 * @returns {number} the number of module which are contained in this chunk | ||||
| 	 * @returns {number} the number of modules which are contained in this chunk | ||||
| 	 */ | ||||
| 	getNumberOfChunkModules(chunk) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		return cgc.modules.size; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk | ||||
| 	 * @returns {number} the number of full hash modules which are contained in this chunk | ||||
| 	 */ | ||||
| 	getNumberOfChunkFullHashModules(chunk) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		return cgc.fullHashModules === undefined ? 0 : cgc.fullHashModules.size; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk | ||||
| 	 * @returns {Iterable<Module>} return the modules for this chunk | ||||
|  | @ -900,6 +936,23 @@ class ChunkGraph { | |||
| 		ChunkGraph.clearChunkGraphForChunk(chunkB); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk to upgrade | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	upgradeDependentToFullHashModules(chunk) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		if (cgc.dependentHashModules === undefined) return; | ||||
| 		if (cgc.fullHashModules === undefined) { | ||||
| 			cgc.fullHashModules = cgc.dependentHashModules; | ||||
| 		} else { | ||||
| 			for (const m of cgc.dependentHashModules) { | ||||
| 				cgc.fullHashModules.add(m); | ||||
| 			} | ||||
| 			cgc.dependentHashModules = undefined; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Module} module the checked module | ||||
| 	 * @param {Chunk} chunk the checked chunk | ||||
|  | @ -952,6 +1005,18 @@ class ChunkGraph { | |||
| 		cgc.fullHashModules.add(module); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the new chunk | ||||
| 	 * @param {RuntimeModule} module the module that require a full hash | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	addDependentHashModuleToChunk(chunk, module) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		if (cgc.dependentHashModules === undefined) | ||||
| 			cgc.dependentHashModules = new Set(); | ||||
| 		cgc.dependentHashModules.add(module); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the new chunk | ||||
| 	 * @param {Module} module the entry module | ||||
|  | @ -1128,6 +1193,15 @@ class ChunkGraph { | |||
| 		return cgc.fullHashModules; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {Chunk} chunk the chunk | ||||
| 	 * @returns {Iterable<RuntimeModule> | undefined} iterable of modules (do not modify) | ||||
| 	 */ | ||||
| 	getChunkDependentHashModulesIterable(chunk) { | ||||
| 		const cgc = this._getChunkGraphChunk(chunk); | ||||
| 		return cgc.dependentHashModules; | ||||
| 	} | ||||
| 
 | ||||
| 	/** @typedef {[Module, Entrypoint | undefined]} EntryModuleWithChunkGroup */ | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -2879,6 +2879,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o | |||
| 		chunkGraph.connectChunkAndRuntimeModule(chunk, module); | ||||
| 		if (module.fullHash) { | ||||
| 			chunkGraph.addFullHashModuleToChunk(chunk, module); | ||||
| 		} else if (module.dependentHash) { | ||||
| 			chunkGraph.addDependentHashModuleToChunk(chunk, module); | ||||
| 		} | ||||
| 
 | ||||
| 		// attach runtime module
 | ||||
|  | @ -3344,8 +3346,13 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o | |||
| 		if (remaining > 0) { | ||||
| 			const readyChunks = []; | ||||
| 			for (const chunk of runtimeChunks) { | ||||
| 				const hasFullHashModules = | ||||
| 					chunkGraph.getNumberOfChunkFullHashModules(chunk) !== 0; | ||||
| 				const info = runtimeChunksMap.get(chunk); | ||||
| 				for (const otherInfo of info.referencedBy) { | ||||
| 					if (hasFullHashModules) { | ||||
| 						chunkGraph.upgradeDependentToFullHashModules(otherInfo.chunk); | ||||
| 					} | ||||
| 					remaining--; | ||||
| 					if (--otherInfo.remaining === 0) { | ||||
| 						readyChunks.push(otherInfo.chunk); | ||||
|  |  | |||
|  | @ -495,6 +495,7 @@ class HotModuleReplacementPlugin { | |||
| 							let newModules; | ||||
| 							let newRuntimeModules; | ||||
| 							let newFullHashModules; | ||||
| 							let newDependentHashModules; | ||||
| 							let newRuntime; | ||||
| 							let removedFromRuntime; | ||||
| 							const currentChunk = find( | ||||
|  | @ -521,6 +522,13 @@ class HotModuleReplacementPlugin { | |||
| 									Array.from(fullHashModules).filter(module => | ||||
| 										updatedModules.has(module, currentChunk) | ||||
| 									); | ||||
| 								const dependentHashModules = | ||||
| 									chunkGraph.getChunkDependentHashModulesIterable(currentChunk); | ||||
| 								newDependentHashModules = | ||||
| 									dependentHashModules && | ||||
| 									Array.from(dependentHashModules).filter(module => | ||||
| 										updatedModules.has(module, currentChunk) | ||||
| 									); | ||||
| 								removedFromRuntime = subtractRuntime(oldRuntime, newRuntime); | ||||
| 							} else { | ||||
| 								// chunk has completely removed
 | ||||
|  | @ -607,6 +615,12 @@ class HotModuleReplacementPlugin { | |||
| 										newFullHashModules | ||||
| 									); | ||||
| 								} | ||||
| 								if (newDependentHashModules) { | ||||
| 									chunkGraph.attachDependentHashModules( | ||||
| 										hotUpdateChunk, | ||||
| 										newDependentHashModules | ||||
| 									); | ||||
| 								} | ||||
| 								const renderManifest = compilation.getRenderManifest({ | ||||
| 									chunk: hotUpdateChunk, | ||||
| 									hash: records.hash, | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ class RuntimeModule extends Module { | |||
| 		/** @type {ChunkGraph} */ | ||||
| 		this.chunkGraph = undefined; | ||||
| 		this.fullHash = false; | ||||
| 		this.dependentHash = false; | ||||
| 		/** @type {string} */ | ||||
| 		this._cachedGeneratedCode = undefined; | ||||
| 	} | ||||
|  | @ -107,7 +108,7 @@ class RuntimeModule extends Module { | |||
| 		hash.update(this.name); | ||||
| 		hash.update(`${this.stage}`); | ||||
| 		try { | ||||
| 			if (this.fullHash) { | ||||
| 			if (this.fullHash || this.dependentHash) { | ||||
| 				// Do not use getGeneratedCode here, because i. e. compilation hash might be not
 | ||||
| 				// ready at this point. We will cache it later instead.
 | ||||
| 				hash.update(this.generate()); | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ class GetChunkFilenameRuntimeModule extends RuntimeModule { | |||
| 		this.global = global; | ||||
| 		this.getFilenameForChunk = getFilenameForChunk; | ||||
| 		this.allChunks = allChunks; | ||||
| 		this.dependentHash = true; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	output: { | ||||
| 		filename: "[name].js" | ||||
|  |  | |||
|  | @ -0,0 +1,20 @@ | |||
| import { Worker } from "worker_threads"; | ||||
| 
 | ||||
| it("should allow to create a WebWorker", async () => { | ||||
| 	const worker = new Worker( | ||||
| 		new URL("./worker.js" + __resourceQuery, import.meta.url) | ||||
| 	); | ||||
| 	worker.postMessage("ok"); | ||||
| 	const result = await new Promise(resolve => { | ||||
| 		worker.on("message", data => { | ||||
| 			resolve(data); | ||||
| 		}); | ||||
| 	}); | ||||
| 	expect(result).toBe("data: OK, thanks"); | ||||
| 	await worker.terminate(); | ||||
| }); | ||||
| 
 | ||||
| it("should allow to share chunks", async () => { | ||||
| 	const { upper } = await import("./module"); | ||||
| 	expect(upper("ok")).toBe("OK"); | ||||
| }); | ||||
|  | @ -0,0 +1,3 @@ | |||
| export function upper(str) { | ||||
| 	return str.toUpperCase(); | ||||
| } | ||||
|  | @ -0,0 +1,5 @@ | |||
| module.exports = { | ||||
| 	findBundle: function (i, options) { | ||||
| 		return ["a.js", "b.js", "c.js", "d.js"]; | ||||
| 	} | ||||
| }; | ||||
|  | @ -0,0 +1,5 @@ | |||
| var supportsWorker = require("../../../helpers/supportsWorker"); | ||||
| 
 | ||||
| module.exports = function (config) { | ||||
| 	return supportsWorker(); | ||||
| }; | ||||
|  | @ -0,0 +1,15 @@ | |||
| const webpack = require("../../../../"); | ||||
| 
 | ||||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	entry: { | ||||
| 		a: { import: "./index.js?a", filename: "[name].js" }, | ||||
| 		b: { import: "./index.js?b", filename: "[name].js" }, | ||||
| 		c: { import: "./index.js?c", filename: "[name].js" }, | ||||
| 		d: { import: "./index.js?d", filename: "[name].js" } | ||||
| 	}, | ||||
| 	output: { | ||||
| 		filename: "[name].[contenthash].js" | ||||
| 	}, | ||||
| 	plugins: [new webpack.HotModuleReplacementPlugin()] | ||||
| }; | ||||
|  | @ -0,0 +1,6 @@ | |||
| import { parentPort } from "worker_threads"; | ||||
| 
 | ||||
| parentPort.on("message", async data => { | ||||
| 	const { upper } = await import("./module"); | ||||
| 	parentPort.postMessage(`data: ${upper(data)}, thanks`); | ||||
| }); | ||||
|  | @ -1,3 +1,4 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	output: { | ||||
| 		filename: "[name].js" | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	entry: { | ||||
| 		a: { import: "./index.js?a", filename: "[name].js" }, | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	output: { | ||||
| 		filename: "[name].js" | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| /** @type {import("../../../../").Configuration} */ | ||||
| module.exports = { | ||||
| 	entry: { | ||||
| 		main: { | ||||
|  |  | |||
|  | @ -767,6 +767,10 @@ declare class ChunkGraph { | |||
| 	attachModules(chunk: Chunk, modules: Iterable<Module>): void; | ||||
| 	attachRuntimeModules(chunk: Chunk, modules: Iterable<RuntimeModule>): void; | ||||
| 	attachFullHashModules(chunk: Chunk, modules: Iterable<RuntimeModule>): void; | ||||
| 	attachDependentHashModules( | ||||
| 		chunk: Chunk, | ||||
| 		modules: Iterable<RuntimeModule> | ||||
| 	): void; | ||||
| 	replaceModule(oldModule: Module, newModule: Module): void; | ||||
| 	isModuleInChunk(module: Module, chunk: Chunk): boolean; | ||||
| 	isModuleInChunkGroup(module: Module, chunkGroup: ChunkGroup): boolean; | ||||
|  | @ -780,6 +784,7 @@ declare class ChunkGraph { | |||
| 	getNumberOfModuleChunks(module: Module): number; | ||||
| 	getModuleRuntimes(module: Module): RuntimeSpecSet; | ||||
| 	getNumberOfChunkModules(chunk: Chunk): number; | ||||
| 	getNumberOfChunkFullHashModules(chunk: Chunk): number; | ||||
| 	getChunkModulesIterable(chunk: Chunk): Iterable<Module>; | ||||
| 	getChunkModulesIterableBySourceType( | ||||
| 		chunk: Chunk, | ||||
|  | @ -831,6 +836,7 @@ declare class ChunkGraph { | |||
| 	): number; | ||||
| 	canChunksBeIntegrated(chunkA: Chunk, chunkB: Chunk): boolean; | ||||
| 	integrateChunks(chunkA: Chunk, chunkB: Chunk): void; | ||||
| 	upgradeDependentToFullHashModules(chunk: Chunk): void; | ||||
| 	isEntryModuleInChunk(module: Module, chunk: Chunk): boolean; | ||||
| 	connectChunkAndEntryModule( | ||||
| 		chunk: Chunk, | ||||
|  | @ -839,6 +845,7 @@ declare class ChunkGraph { | |||
| 	): void; | ||||
| 	connectChunkAndRuntimeModule(chunk: Chunk, module: RuntimeModule): void; | ||||
| 	addFullHashModuleToChunk(chunk: Chunk, module: RuntimeModule): void; | ||||
| 	addDependentHashModuleToChunk(chunk: Chunk, module: RuntimeModule): void; | ||||
| 	disconnectChunkAndEntryModule(chunk: Chunk, module: Module): void; | ||||
| 	disconnectChunkAndRuntimeModule(chunk: Chunk, module: RuntimeModule): void; | ||||
| 	disconnectEntryModule(module: Module): void; | ||||
|  | @ -856,6 +863,9 @@ declare class ChunkGraph { | |||
| 	getChunkFullHashModulesSet( | ||||
| 		chunk: Chunk | ||||
| 	): undefined | ReadonlySet<RuntimeModule>; | ||||
| 	getChunkDependentHashModulesIterable( | ||||
| 		chunk: Chunk | ||||
| 	): undefined | Iterable<RuntimeModule>; | ||||
| 	getChunkEntryModulesWithChunkGroupIterable( | ||||
| 		chunk: Chunk | ||||
| 	): Iterable<[Module, undefined | Entrypoint]>; | ||||
|  | @ -9779,6 +9789,7 @@ declare class RuntimeModule extends Module { | |||
| 	chunk: Chunk; | ||||
| 	chunkGraph: ChunkGraph; | ||||
| 	fullHash: boolean; | ||||
| 	dependentHash: boolean; | ||||
| 	attach(compilation: Compilation, chunk: Chunk, chunkGraph?: ChunkGraph): void; | ||||
| 	generate(): string; | ||||
| 	getGeneratedCode(): string; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue