| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-22 19:05:58 +08:00
										 |  |  | const { ConcatSource } = require("webpack-sources"); | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | const HotUpdateChunk = require("./HotUpdateChunk"); | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | const JavascriptGenerator = require("./JavascriptGenerator"); | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | const JavascriptParser = require("./JavascriptParser"); | 
					
						
							|  |  |  | const Template = require("./Template"); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | const { compareModulesById } = require("./util/comparators"); | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | const createHash = require("./util/createHash"); | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | /** @typedef {import("webpack-sources").Source} Source */ | 
					
						
							| 
									
										
										
										
											2018-08-23 22:54:02 +08:00
										 |  |  | /** @typedef {import("./Chunk")} Chunk */ | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | /** @typedef {import("./ChunkTemplate")} ChunkTemplate */ | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | /** @typedef {import("./Compilation")} Compilation */ | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | /** @typedef {import("./Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2018-08-23 22:54:02 +08:00
										 |  |  | /** @typedef {import("./Module")} Module */ | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | /** @typedef {import("./ModuleTemplate")} ModuleTemplate */ | 
					
						
							|  |  |  | /** @typedef {import("./ModuleTemplate").RenderContext} RenderContext */ | 
					
						
							|  |  |  | /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | class JavascriptModulesPlugin { | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {Compiler} compiler webpack compiler | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		compiler.hooks.compilation.tap( | 
					
						
							|  |  |  | 			"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 			(compilation, { normalModuleFactory }) => { | 
					
						
							| 
									
										
										
										
											2018-08-16 22:11:20 +08:00
										 |  |  | 				const moduleGraph = compilation.moduleGraph; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/auto") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							| 
									
										
										
										
											2018-07-03 16:15:48 +08:00
										 |  |  | 						return new JavascriptParser(options, "auto"); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/dynamic") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							| 
									
										
										
										
											2018-07-03 16:15:48 +08:00
										 |  |  | 						return new JavascriptParser(options, "script"); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/esm") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							| 
									
										
										
										
											2018-07-03 16:15:48 +08:00
										 |  |  | 						return new JavascriptParser(options, "module"); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createGenerator | 
					
						
							|  |  |  | 					.for("javascript/auto") | 
					
						
							| 
									
										
										
										
											2018-03-28 11:16:12 +08:00
										 |  |  | 					.tap("JavascriptModulesPlugin", () => { | 
					
						
							|  |  |  | 						return new JavascriptGenerator(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createGenerator | 
					
						
							|  |  |  | 					.for("javascript/dynamic") | 
					
						
							| 
									
										
										
										
											2018-03-28 11:16:12 +08:00
										 |  |  | 					.tap("JavascriptModulesPlugin", () => { | 
					
						
							|  |  |  | 						return new JavascriptGenerator(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createGenerator | 
					
						
							|  |  |  | 					.for("javascript/esm") | 
					
						
							| 
									
										
										
										
											2018-03-28 11:16:12 +08:00
										 |  |  | 					.tap("JavascriptModulesPlugin", () => { | 
					
						
							|  |  |  | 						return new JavascriptGenerator(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					}); | 
					
						
							|  |  |  | 				compilation.mainTemplate.hooks.renderManifest.tap( | 
					
						
							|  |  |  | 					"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 					(result, options) => { | 
					
						
							|  |  |  | 						const chunk = options.chunk; | 
					
						
							|  |  |  | 						const hash = options.hash; | 
					
						
							|  |  |  | 						const outputOptions = options.outputOptions; | 
					
						
							|  |  |  | 						const moduleTemplates = options.moduleTemplates; | 
					
						
							|  |  |  | 						const dependencyTemplates = options.dependencyTemplates; | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 						const filenameTemplate = | 
					
						
							|  |  |  | 							chunk.filenameTemplate || outputOptions.filename; | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						result.push({ | 
					
						
							|  |  |  | 							render: () => | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 								compilation.mainTemplate.render(moduleTemplates.javascript, { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									hash, | 
					
						
							|  |  |  | 									chunk, | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 									dependencyTemplates, | 
					
						
							|  |  |  | 									runtimeTemplate: options.runtimeTemplate, | 
					
						
							|  |  |  | 									moduleGraph: options.moduleGraph, | 
					
						
							|  |  |  | 									chunkGraph: options.chunkGraph | 
					
						
							|  |  |  | 								}), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							filenameTemplate, | 
					
						
							|  |  |  | 							pathOptions: { | 
					
						
							| 
									
										
										
										
											2018-09-28 19:10:37 +08:00
										 |  |  | 								chunk, | 
					
						
							|  |  |  | 								contentHashType: "javascript" | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							}, | 
					
						
							|  |  |  | 							identifier: `chunk${chunk.id}`, | 
					
						
							| 
									
										
										
										
											2018-10-23 23:09:32 +08:00
										 |  |  | 							hash: chunk.hash | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						}); | 
					
						
							|  |  |  | 						return result; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				compilation.mainTemplate.hooks.modules.tap( | 
					
						
							|  |  |  | 					"JavascriptModulesPlugin", | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 					(source, moduleTemplate, renderContext) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						return Template.renderChunkModules( | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 							renderContext, | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | 							m => m.getSourceTypes().has("javascript"), | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							moduleTemplate, | 
					
						
							|  |  |  | 							"/******/ " | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				compilation.chunkTemplate.hooks.renderManifest.tap( | 
					
						
							|  |  |  | 					"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 					(result, options) => { | 
					
						
							|  |  |  | 						const chunk = options.chunk; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 						const hotUpdateChunk = | 
					
						
							|  |  |  | 							chunk instanceof HotUpdateChunk ? chunk : null; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						const outputOptions = options.outputOptions; | 
					
						
							|  |  |  | 						const moduleTemplates = options.moduleTemplates; | 
					
						
							|  |  |  | 						const dependencyTemplates = options.dependencyTemplates; | 
					
						
							| 
									
										
										
										
											2018-05-25 22:12:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						let filenameTemplate; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 						if (hotUpdateChunk) { | 
					
						
							|  |  |  | 							filenameTemplate = outputOptions.hotUpdateChunkFilename; | 
					
						
							|  |  |  | 						} else if (chunk.filenameTemplate) { | 
					
						
							| 
									
										
										
										
											2018-05-25 22:12:40 +08:00
										 |  |  | 							filenameTemplate = chunk.filenameTemplate; | 
					
						
							| 
									
										
										
										
											2018-06-27 19:55:01 +08:00
										 |  |  | 						} else if (chunk.isOnlyInitial()) { | 
					
						
							| 
									
										
										
										
											2018-05-25 22:12:40 +08:00
										 |  |  | 							filenameTemplate = outputOptions.filename; | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							filenameTemplate = outputOptions.chunkFilename; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						result.push({ | 
					
						
							|  |  |  | 							render: () => | 
					
						
							|  |  |  | 								this.renderJavascript( | 
					
						
							| 
									
										
										
										
											2018-08-23 22:54:02 +08:00
										 |  |  | 									compilation, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 									compilation.chunkTemplate, | 
					
						
							|  |  |  | 									moduleTemplates.javascript, | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 									{ | 
					
						
							|  |  |  | 										chunk, | 
					
						
							|  |  |  | 										dependencyTemplates, | 
					
						
							|  |  |  | 										runtimeTemplate: compilation.runtimeTemplate, | 
					
						
							| 
									
										
										
										
											2018-08-22 17:49:27 +08:00
										 |  |  | 										moduleGraph, | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 										chunkGraph: compilation.chunkGraph | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 									} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								), | 
					
						
							|  |  |  | 							filenameTemplate, | 
					
						
							|  |  |  | 							pathOptions: { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 								hash: options.hash, | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 								chunk, | 
					
						
							|  |  |  | 								contentHashType: "javascript" | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							}, | 
					
						
							|  |  |  | 							identifier: `chunk${chunk.id}`, | 
					
						
							|  |  |  | 							hash: chunk.hash | 
					
						
							|  |  |  | 						}); | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						return result; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 				compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => { | 
					
						
							| 
									
										
										
										
											2018-03-24 18:21:41 +08:00
										 |  |  | 					const { | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						chunkGraph, | 
					
						
							| 
									
										
										
										
											2018-09-15 19:10:58 +08:00
										 |  |  | 						moduleGraph, | 
					
						
							|  |  |  | 						runtimeTemplate, | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 						outputOptions: { | 
					
						
							|  |  |  | 							hashSalt, | 
					
						
							|  |  |  | 							hashDigest, | 
					
						
							|  |  |  | 							hashDigestLength, | 
					
						
							|  |  |  | 							hashFunction | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} = compilation; | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 					const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null; | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 					const hash = createHash(hashFunction); | 
					
						
							|  |  |  | 					if (hashSalt) hash.update(hashSalt); | 
					
						
							|  |  |  | 					const template = chunk.hasRuntime() | 
					
						
							|  |  |  | 						? compilation.mainTemplate | 
					
						
							|  |  |  | 						: compilation.chunkTemplate; | 
					
						
							| 
									
										
										
										
											2018-08-20 15:47:10 +08:00
										 |  |  | 					hash.update(`${chunk.id} `); | 
					
						
							|  |  |  | 					hash.update(chunk.ids ? chunk.ids.join(",") : ""); | 
					
						
							| 
									
										
										
										
											2018-09-15 19:10:58 +08:00
										 |  |  | 					template.updateHashForChunk(hash, chunk, { | 
					
						
							|  |  |  | 						chunkGraph, | 
					
						
							|  |  |  | 						moduleGraph, | 
					
						
							|  |  |  | 						runtimeTemplate | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					for (const m of chunkGraph.getOrderedChunkModulesIterable( | 
					
						
							|  |  |  | 						chunk, | 
					
						
							| 
									
										
										
										
											2018-08-28 17:50:33 +08:00
										 |  |  | 						compareModulesById(chunkGraph) | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					)) { | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | 						if (m.getSourceTypes().has("javascript")) { | 
					
						
							| 
									
										
										
										
											2018-08-23 01:23:48 +08:00
										 |  |  | 							hash.update(chunkGraph.getModuleHash(m)); | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 					if (hotUpdateChunk) { | 
					
						
							|  |  |  | 						hash.update(JSON.stringify(hotUpdateChunk.removedModules)); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 					chunk.contentHash.javascript = hash | 
					
						
							|  |  |  | 						.digest(hashDigest) | 
					
						
							|  |  |  | 						.substr(0, hashDigestLength); | 
					
						
							|  |  |  | 				}); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2018-08-23 22:54:02 +08:00
										 |  |  | 	 * @param {Compilation} compilation the compilation | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 	 * @param {ChunkTemplate} chunkTemplate the chunk template | 
					
						
							|  |  |  | 	 * @param {ModuleTemplate} moduleTemplate the module template | 
					
						
							|  |  |  | 	 * @param {RenderContext} renderContext the render context | 
					
						
							|  |  |  | 	 * @returns {Source} the rendered source | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-08-23 22:54:02 +08:00
										 |  |  | 	renderJavascript(compilation, chunkTemplate, moduleTemplate, renderContext) { | 
					
						
							|  |  |  | 		const chunk = renderContext.chunk; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		const moduleSources = Template.renderChunkModules( | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 			renderContext, | 
					
						
							| 
									
										
										
										
											2018-12-03 22:00:32 +08:00
										 |  |  | 			m => m.getSourceTypes().has("javascript"), | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 			moduleTemplate | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 		const core = chunkTemplate.hooks.modules.call( | 
					
						
							|  |  |  | 			moduleSources, | 
					
						
							|  |  |  | 			moduleTemplate, | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 			renderContext | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 		let source = chunkTemplate.hooks.render.call( | 
					
						
							|  |  |  | 			core, | 
					
						
							|  |  |  | 			moduleTemplate, | 
					
						
							| 
									
										
										
										
											2018-07-24 23:35:36 +08:00
										 |  |  | 			renderContext | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		); | 
					
						
							| 
									
										
										
										
											2018-08-14 22:40:37 +08:00
										 |  |  | 		if (renderContext.chunkGraph.getNumberOfEntryModules(chunk) > 0) { | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 			source = chunkTemplate.hooks.renderWithEntry.call(source, chunk); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		chunk.rendered = true; | 
					
						
							|  |  |  | 		return new ConcatSource(source, ";"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = JavascriptModulesPlugin; |