| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Parser = require("./Parser"); | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | const Template = require("./Template"); | 
					
						
							| 
									
										
										
										
											2018-03-22 19:05:58 +08:00
										 |  |  | const { ConcatSource } = require("webpack-sources"); | 
					
						
							| 
									
										
										
										
											2018-01-24 06:09:26 +08:00
										 |  |  | const JavascriptGenerator = require("./JavascriptGenerator"); | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | const createHash = require("./util/createHash"); | 
					
						
							| 
									
										
										
										
											2017-11-10 18:02:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class JavascriptModulesPlugin { | 
					
						
							|  |  |  | 	apply(compiler) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		compiler.hooks.compilation.tap( | 
					
						
							|  |  |  | 			"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 			(compilation, { normalModuleFactory }) => { | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/auto") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							|  |  |  | 						return new Parser(options, "auto"); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/dynamic") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							|  |  |  | 						return new Parser(options, "script"); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				normalModuleFactory.hooks.createParser | 
					
						
							|  |  |  | 					.for("javascript/esm") | 
					
						
							|  |  |  | 					.tap("JavascriptModulesPlugin", options => { | 
					
						
							|  |  |  | 						return new Parser(options, "module"); | 
					
						
							|  |  |  | 					}); | 
					
						
							|  |  |  | 				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 fullHash = options.fullHash; | 
					
						
							|  |  |  | 						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
										 |  |  | 						const useChunkHash = compilation.mainTemplate.useChunkHash(chunk); | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						result.push({ | 
					
						
							|  |  |  | 							render: () => | 
					
						
							|  |  |  | 								compilation.mainTemplate.render( | 
					
						
							|  |  |  | 									hash, | 
					
						
							|  |  |  | 									chunk, | 
					
						
							|  |  |  | 									moduleTemplates.javascript, | 
					
						
							|  |  |  | 									dependencyTemplates | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 							filenameTemplate, | 
					
						
							|  |  |  | 							pathOptions: { | 
					
						
							|  |  |  | 								noChunkHash: !useChunkHash, | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 								contentHashType: "javascript", | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								chunk | 
					
						
							|  |  |  | 							}, | 
					
						
							|  |  |  | 							identifier: `chunk${chunk.id}`, | 
					
						
							|  |  |  | 							hash: useChunkHash ? chunk.hash : fullHash | 
					
						
							|  |  |  | 						}); | 
					
						
							|  |  |  | 						return result; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				compilation.mainTemplate.hooks.modules.tap( | 
					
						
							|  |  |  | 					"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 					(source, chunk, hash, moduleTemplate, dependencyTemplates) => { | 
					
						
							|  |  |  | 						return Template.renderChunkModules( | 
					
						
							|  |  |  | 							chunk, | 
					
						
							| 
									
										
										
										
											2018-03-03 22:41:30 +08:00
										 |  |  | 							m => typeof m.source === "function", | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							moduleTemplate, | 
					
						
							|  |  |  | 							dependencyTemplates, | 
					
						
							|  |  |  | 							"/******/ " | 
					
						
							|  |  |  | 						); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				compilation.chunkTemplate.hooks.renderManifest.tap( | 
					
						
							|  |  |  | 					"JavascriptModulesPlugin", | 
					
						
							|  |  |  | 					(result, options) => { | 
					
						
							|  |  |  | 						const chunk = options.chunk; | 
					
						
							|  |  |  | 						const outputOptions = options.outputOptions; | 
					
						
							|  |  |  | 						const moduleTemplates = options.moduleTemplates; | 
					
						
							|  |  |  | 						const dependencyTemplates = options.dependencyTemplates; | 
					
						
							| 
									
										
										
										
											2018-05-29 20:50:40 +08:00
										 |  |  | 						const filenameTemplate = | 
					
						
							|  |  |  | 							chunk.filenameTemplate || outputOptions.chunkFilename; | 
					
						
							| 
									
										
										
										
											2018-01-24 16:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						result.push({ | 
					
						
							|  |  |  | 							render: () => | 
					
						
							|  |  |  | 								this.renderJavascript( | 
					
						
							|  |  |  | 									compilation.chunkTemplate, | 
					
						
							|  |  |  | 									chunk, | 
					
						
							|  |  |  | 									moduleTemplates.javascript, | 
					
						
							|  |  |  | 									dependencyTemplates | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 							filenameTemplate, | 
					
						
							|  |  |  | 							pathOptions: { | 
					
						
							| 
									
										
										
										
											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 => { | 
					
						
							|  |  |  | 					const outputOptions = compilation.outputOptions; | 
					
						
							| 
									
										
										
										
											2018-03-24 18:21:41 +08:00
										 |  |  | 					const { | 
					
						
							|  |  |  | 						hashSalt, | 
					
						
							|  |  |  | 						hashDigest, | 
					
						
							|  |  |  | 						hashDigestLength, | 
					
						
							|  |  |  | 						hashFunction | 
					
						
							|  |  |  | 					} = outputOptions; | 
					
						
							| 
									
										
										
										
											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-14 05:25:26 +08:00
										 |  |  | 					template.updateHashForChunk( | 
					
						
							|  |  |  | 						hash, | 
					
						
							|  |  |  | 						chunk, | 
					
						
							|  |  |  | 						compilation.moduleTemplates.javascript, | 
					
						
							|  |  |  | 						compilation.dependencyTemplates | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2018-03-23 02:52:11 +08:00
										 |  |  | 					for (const m of chunk.modulesIterable) { | 
					
						
							|  |  |  | 						if (typeof m.source === "function") { | 
					
						
							|  |  |  | 							hash.update(m.hash); | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					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
										 |  |  | 
 | 
					
						
							|  |  |  | 	renderJavascript(chunkTemplate, chunk, moduleTemplate, dependencyTemplates) { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		const moduleSources = Template.renderChunkModules( | 
					
						
							|  |  |  | 			chunk, | 
					
						
							| 
									
										
										
										
											2018-03-03 22:41:30 +08:00
										 |  |  | 			m => typeof m.source === "function", | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			moduleTemplate, | 
					
						
							|  |  |  | 			dependencyTemplates | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		const core = chunkTemplate.hooks.modules.call( | 
					
						
							|  |  |  | 			moduleSources, | 
					
						
							|  |  |  | 			chunk, | 
					
						
							|  |  |  | 			moduleTemplate, | 
					
						
							|  |  |  | 			dependencyTemplates | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		let source = chunkTemplate.hooks.render.call( | 
					
						
							|  |  |  | 			core, | 
					
						
							|  |  |  | 			chunk, | 
					
						
							|  |  |  | 			moduleTemplate, | 
					
						
							|  |  |  | 			dependencyTemplates | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		if (chunk.hasEntryModule()) { | 
					
						
							| 
									
										
										
										
											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; |