You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							202 lines
						
					
					
						
							5.9 KiB
						
					
					
				
			
		
		
	
	
							202 lines
						
					
					
						
							5.9 KiB
						
					
					
				| /* | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php | |
| 	Author Tobias Koppers @sokra | |
| */ | |
| 
 | |
| "use strict"; | |
| 
 | |
| const { ConcatSource } = require("webpack-sources"); | |
| const { RuntimeGlobals } = require(".."); | |
| const HotUpdateChunk = require("../HotUpdateChunk"); | |
| const Template = require("../Template"); | |
| const { getAllChunks } = require("../javascript/ChunkHelpers"); | |
| const { | |
| 	getCompilationHooks, | |
| 	getChunkFilenameTemplate | |
| } = require("../javascript/JavascriptModulesPlugin"); | |
| const { updateHashForEntryStartup } = require("../javascript/StartupHelpers"); | |
| 
 | |
| /** @typedef {import("../Compiler")} Compiler */ | |
| 
 | |
| class ModuleChunkFormatPlugin { | |
| 	/** | |
| 	 * Apply the plugin | |
| 	 * @param {Compiler} compiler the compiler instance | |
| 	 * @returns {void} | |
| 	 */ | |
| 	apply(compiler) { | |
| 		compiler.hooks.thisCompilation.tap( | |
| 			"ModuleChunkFormatPlugin", | |
| 			compilation => { | |
| 				compilation.hooks.additionalChunkRuntimeRequirements.tap( | |
| 					"ModuleChunkFormatPlugin", | |
| 					(chunk, set) => { | |
| 						if (chunk.hasRuntime()) return; | |
| 						if (compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0) { | |
| 							set.add(RuntimeGlobals.require); | |
| 							set.add(RuntimeGlobals.startupEntrypoint); | |
| 							set.add(RuntimeGlobals.externalInstallChunk); | |
| 						} | |
| 					} | |
| 				); | |
| 				const hooks = getCompilationHooks(compilation); | |
| 				hooks.renderChunk.tap( | |
| 					"ModuleChunkFormatPlugin", | |
| 					(modules, renderContext) => { | |
| 						const { chunk, chunkGraph, runtimeTemplate } = renderContext; | |
| 						const hotUpdateChunk = | |
| 							chunk instanceof HotUpdateChunk ? chunk : null; | |
| 						const source = new ConcatSource(); | |
| 						if (hotUpdateChunk) { | |
| 							throw new Error( | |
| 								"HMR is not implemented for module chunk format yet" | |
| 							); | |
| 						} else { | |
| 							source.add(`export const id = ${JSON.stringify(chunk.id)};\n`); | |
| 							source.add(`export const ids = ${JSON.stringify(chunk.ids)};\n`); | |
| 							source.add(`export const modules = `); | |
| 							source.add(modules); | |
| 							source.add(`;\n`); | |
| 							const runtimeModules = | |
| 								chunkGraph.getChunkRuntimeModulesInOrder(chunk); | |
| 							if (runtimeModules.length > 0) { | |
| 								source.add("export const runtime =\n"); | |
| 								source.add( | |
| 									Template.renderChunkRuntimeModules( | |
| 										runtimeModules, | |
| 										renderContext | |
| 									) | |
| 								); | |
| 							} | |
| 							const entries = Array.from( | |
| 								chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk) | |
| 							); | |
| 							if (entries.length > 0) { | |
| 								const runtimeChunk = entries[0][1].getRuntimeChunk(); | |
| 								const currentOutputName = compilation | |
| 									.getPath( | |
| 										getChunkFilenameTemplate(chunk, compilation.outputOptions), | |
| 										{ | |
| 											chunk, | |
| 											contentHashType: "javascript" | |
| 										} | |
| 									) | |
| 									.split("/"); | |
| 
 | |
| 								// remove filename, we only need the directory | |
| 								currentOutputName.pop(); | |
| 
 | |
| 								const getRelativePath = chunk => { | |
| 									const baseOutputName = currentOutputName.slice(); | |
| 									const chunkOutputName = compilation | |
| 										.getPath( | |
| 											getChunkFilenameTemplate( | |
| 												chunk, | |
| 												compilation.outputOptions | |
| 											), | |
| 											{ | |
| 												chunk: chunk, | |
| 												contentHashType: "javascript" | |
| 											} | |
| 										) | |
| 										.split("/"); | |
| 
 | |
| 									// remove common parts | |
| 									while ( | |
| 										baseOutputName.length > 0 && | |
| 										chunkOutputName.length > 0 && | |
| 										baseOutputName[0] === chunkOutputName[0] | |
| 									) { | |
| 										baseOutputName.shift(); | |
| 										chunkOutputName.shift(); | |
| 									} | |
| 									// create final path | |
| 									return ( | |
| 										(baseOutputName.length > 0 | |
| 											? "../".repeat(baseOutputName.length) | |
| 											: "./") + chunkOutputName.join("/") | |
| 									); | |
| 								}; | |
| 
 | |
| 								const entrySource = new ConcatSource(); | |
| 								entrySource.add(source); | |
| 								entrySource.add(";\n\n// load runtime\n"); | |
| 								entrySource.add( | |
| 									`import __webpack_require__ from ${JSON.stringify( | |
| 										getRelativePath(runtimeChunk) | |
| 									)};\n` | |
| 								); | |
| 
 | |
| 								const startupSource = new ConcatSource(); | |
| 								startupSource.add( | |
| 									`var __webpack_exec__ = ${runtimeTemplate.returningFunction( | |
| 										`__webpack_require__(${RuntimeGlobals.entryModuleId} = moduleId)`, | |
| 										"moduleId" | |
| 									)}\n` | |
| 								); | |
| 
 | |
| 								const loadedChunks = new Set(); | |
| 								let index = 0; | |
| 								for (let i = 0; i < entries.length; i++) { | |
| 									const [module, entrypoint] = entries[i]; | |
| 									const final = i + 1 === entries.length; | |
| 									const moduleId = chunkGraph.getModuleId(module); | |
| 									const chunks = getAllChunks( | |
| 										entrypoint, | |
| 										runtimeChunk, | |
| 										undefined | |
| 									); | |
| 									for (const chunk of chunks) { | |
| 										if (loadedChunks.has(chunk)) continue; | |
| 										loadedChunks.add(chunk); | |
| 										startupSource.add( | |
| 											`import * as __webpack_chunk_${index}__ from ${JSON.stringify( | |
| 												getRelativePath(chunk) | |
| 											)};\n` | |
| 										); | |
| 										startupSource.add( | |
| 											`${RuntimeGlobals.externalInstallChunk}(__webpack_chunk_${index}__);\n` | |
| 										); | |
| 										index++; | |
| 									} | |
| 									startupSource.add( | |
| 										`${ | |
| 											final ? "var __webpack_exports__ = " : "" | |
| 										}__webpack_exec__(${JSON.stringify(moduleId)});\n` | |
| 									); | |
| 								} | |
| 
 | |
| 								entrySource.add( | |
| 									hooks.renderStartup.call( | |
| 										startupSource, | |
| 										entries[entries.length - 1][0], | |
| 										{ | |
| 											...renderContext, | |
| 											inlined: false | |
| 										} | |
| 									) | |
| 								); | |
| 								return entrySource; | |
| 							} | |
| 						} | |
| 						return source; | |
| 					} | |
| 				); | |
| 				hooks.chunkHash.tap( | |
| 					"ModuleChunkFormatPlugin", | |
| 					(chunk, hash, { chunkGraph, runtimeTemplate }) => { | |
| 						if (chunk.hasRuntime()) return; | |
| 						hash.update("ModuleChunkFormatPlugin"); | |
| 						hash.update("1"); | |
| 						const entries = Array.from( | |
| 							chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk) | |
| 						); | |
| 						updateHashForEntryStartup(hash, chunkGraph, entries, chunk); | |
| 					} | |
| 				); | |
| 			} | |
| 		); | |
| 	} | |
| } | |
| 
 | |
| module.exports = ModuleChunkFormatPlugin;
 | |
| 
 |