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.
		
		
		
		
		
			
		
			
				
					
					
						
							321 lines
						
					
					
						
							10 KiB
						
					
					
				
			
		
		
	
	
							321 lines
						
					
					
						
							10 KiB
						
					
					
				/* | 
						|
	MIT License http://www.opensource.org/licenses/mit-license.php | 
						|
	Author Tobias Koppers @sokra | 
						|
*/ | 
						|
"use strict"; | 
						|
 | 
						|
const Template = require("../Template"); | 
						|
 | 
						|
module.exports = class NodeMainTemplatePlugin { | 
						|
	constructor(asyncChunkLoading) { | 
						|
		this.asyncChunkLoading = asyncChunkLoading; | 
						|
	} | 
						|
 | 
						|
	apply(mainTemplate) { | 
						|
		const needChunkOnDemandLoadingCode = chunk => { | 
						|
			for (const chunkGroup of chunk.groupsIterable) { | 
						|
				if (chunkGroup.getNumberOfChildren() > 0) return true; | 
						|
			} | 
						|
			return false; | 
						|
		}; | 
						|
		const asyncChunkLoading = this.asyncChunkLoading; | 
						|
		mainTemplate.hooks.localVars.tap( | 
						|
			"NodeMainTemplatePlugin", | 
						|
			(source, chunk) => { | 
						|
				if (needChunkOnDemandLoadingCode(chunk)) { | 
						|
					return Template.asString([ | 
						|
						source, | 
						|
						"", | 
						|
						"// object to store loaded chunks", | 
						|
						'// "0" means "already loaded"', | 
						|
						"var installedChunks = {", | 
						|
						Template.indent( | 
						|
							chunk.ids.map(id => `${JSON.stringify(id)}: 0`).join(",\n") | 
						|
						), | 
						|
						"};" | 
						|
					]); | 
						|
				} | 
						|
				return source; | 
						|
			} | 
						|
		); | 
						|
		mainTemplate.hooks.requireExtensions.tap( | 
						|
			"NodeMainTemplatePlugin", | 
						|
			(source, chunk) => { | 
						|
				if (needChunkOnDemandLoadingCode(chunk)) { | 
						|
					return Template.asString([ | 
						|
						source, | 
						|
						"", | 
						|
						"// uncaught error handler for webpack runtime", | 
						|
						`${mainTemplate.requireFn}.oe = function(err) {`, | 
						|
						Template.indent([ | 
						|
							"process.nextTick(function() {", | 
						|
							Template.indent( | 
						|
								"throw err; // catch this error by using import().catch()" | 
						|
							), | 
						|
							"});" | 
						|
						]), | 
						|
						"};" | 
						|
					]); | 
						|
				} | 
						|
				return source; | 
						|
			} | 
						|
		); | 
						|
		mainTemplate.hooks.requireEnsure.tap( | 
						|
			"NodeMainTemplatePlugin", | 
						|
			(source, chunk, hash) => { | 
						|
				const chunkFilename = mainTemplate.outputOptions.chunkFilename; | 
						|
				const chunkMaps = chunk.getChunkMaps(); | 
						|
				const insertMoreModules = [ | 
						|
					"var moreModules = chunk.modules, chunkIds = chunk.ids;", | 
						|
					"for(var moduleId in moreModules) {", | 
						|
					Template.indent( | 
						|
						mainTemplate.renderAddModule( | 
						|
							hash, | 
						|
							chunk, | 
						|
							"moduleId", | 
						|
							"moreModules[moduleId]" | 
						|
						) | 
						|
					), | 
						|
					"}" | 
						|
				]; | 
						|
				if (asyncChunkLoading) { | 
						|
					return Template.asString([ | 
						|
						source, | 
						|
						"", | 
						|
						"// ReadFile + VM.run chunk loading for javascript", | 
						|
						"", | 
						|
						"var installedChunkData = installedChunks[chunkId];", | 
						|
						'if(installedChunkData !== 0) { // 0 means "already installed".', | 
						|
						Template.indent([ | 
						|
							'// array of [resolve, reject, promise] means "currently loading"', | 
						|
							"if(installedChunkData) {", | 
						|
							Template.indent(["promises.push(installedChunkData[2]);"]), | 
						|
							"} else {", | 
						|
							Template.indent([ | 
						|
								"// load the chunk and return promise to it", | 
						|
								"var promise = new Promise(function(resolve, reject) {", | 
						|
								Template.indent([ | 
						|
									"installedChunkData = installedChunks[chunkId] = [resolve, reject];", | 
						|
									"var filename = require('path').join(__dirname, " + | 
						|
										mainTemplate.getAssetPath( | 
						|
											JSON.stringify(`/${chunkFilename}`), | 
						|
											{ | 
						|
												hash: `" + ${mainTemplate.renderCurrentHashCode( | 
						|
													hash | 
						|
												)} + "`, | 
						|
												hashWithLength: length => | 
						|
													`" + ${mainTemplate.renderCurrentHashCode( | 
						|
														hash, | 
						|
														length | 
						|
													)} + "`, | 
						|
												chunk: { | 
						|
													id: '" + chunkId + "', | 
						|
													hash: `" + ${JSON.stringify( | 
						|
														chunkMaps.hash | 
						|
													)}[chunkId] + "`, | 
						|
													hashWithLength: length => { | 
						|
														const shortChunkHashMap = {}; | 
						|
														for (const chunkId of Object.keys(chunkMaps.hash)) { | 
						|
															if (typeof chunkMaps.hash[chunkId] === "string") { | 
						|
																shortChunkHashMap[chunkId] = chunkMaps.hash[ | 
						|
																	chunkId | 
						|
																].substr(0, length); | 
						|
															} | 
						|
														} | 
						|
														return `" + ${JSON.stringify( | 
						|
															shortChunkHashMap | 
						|
														)}[chunkId] + "`; | 
						|
													}, | 
						|
													contentHash: { | 
						|
														javascript: `" + ${JSON.stringify( | 
						|
															chunkMaps.contentHash.javascript | 
						|
														)}[chunkId] + "` | 
						|
													}, | 
						|
													contentHashWithLength: { | 
						|
														javascript: length => { | 
						|
															const shortContentHashMap = {}; | 
						|
															const contentHash = | 
						|
																chunkMaps.contentHash.javascript; | 
						|
															for (const chunkId of Object.keys(contentHash)) { | 
						|
																if (typeof contentHash[chunkId] === "string") { | 
						|
																	shortContentHashMap[chunkId] = contentHash[ | 
						|
																		chunkId | 
						|
																	].substr(0, length); | 
						|
																} | 
						|
															} | 
						|
															return `" + ${JSON.stringify( | 
						|
																shortContentHashMap | 
						|
															)}[chunkId] + "`; | 
						|
														} | 
						|
													}, | 
						|
													name: `" + (${JSON.stringify( | 
						|
														chunkMaps.name | 
						|
													)}[chunkId]||chunkId) + "` | 
						|
												}, | 
						|
												contentHashType: "javascript" | 
						|
											} | 
						|
										) + | 
						|
										");", | 
						|
									"require('fs').readFile(filename, 'utf-8',  function(err, content) {", | 
						|
									Template.indent( | 
						|
										[ | 
						|
											"if(err) return reject(err);", | 
						|
											"var chunk = {};", | 
						|
											"require('vm').runInThisContext('(function(exports, require, __dirname, __filename) {' + content + '\\n})', filename)" + | 
						|
												"(chunk, require, require('path').dirname(filename), filename);" | 
						|
										] | 
						|
											.concat(insertMoreModules) | 
						|
											.concat([ | 
						|
												"var callbacks = [];", | 
						|
												"for(var i = 0; i < chunkIds.length; i++) {", | 
						|
												Template.indent([ | 
						|
													"if(installedChunks[chunkIds[i]])", | 
						|
													Template.indent([ | 
						|
														"callbacks = callbacks.concat(installedChunks[chunkIds[i]][0]);" | 
						|
													]), | 
						|
													"installedChunks[chunkIds[i]] = 0;" | 
						|
												]), | 
						|
												"}", | 
						|
												"for(i = 0; i < callbacks.length; i++)", | 
						|
												Template.indent("callbacks[i]();") | 
						|
											]) | 
						|
									), | 
						|
									"});" | 
						|
								]), | 
						|
								"});", | 
						|
								"promises.push(installedChunkData[2] = promise);" | 
						|
							]), | 
						|
							"}" | 
						|
						]), | 
						|
						"}" | 
						|
					]); | 
						|
				} else { | 
						|
					const request = mainTemplate.getAssetPath( | 
						|
						JSON.stringify(`./${chunkFilename}`), | 
						|
						{ | 
						|
							hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, | 
						|
							hashWithLength: length => | 
						|
								`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, | 
						|
							chunk: { | 
						|
								id: '" + chunkId + "', | 
						|
								hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, | 
						|
								hashWithLength: length => { | 
						|
									const shortChunkHashMap = {}; | 
						|
									for (const chunkId of Object.keys(chunkMaps.hash)) { | 
						|
										if (typeof chunkMaps.hash[chunkId] === "string") { | 
						|
											shortChunkHashMap[chunkId] = chunkMaps.hash[ | 
						|
												chunkId | 
						|
											].substr(0, length); | 
						|
										} | 
						|
									} | 
						|
									return `" + ${JSON.stringify( | 
						|
										shortChunkHashMap | 
						|
									)}[chunkId] + "`; | 
						|
								}, | 
						|
								contentHash: { | 
						|
									javascript: `" + ${JSON.stringify( | 
						|
										chunkMaps.contentHash.javascript | 
						|
									)}[chunkId] + "` | 
						|
								}, | 
						|
								contentHashWithLength: { | 
						|
									javascript: length => { | 
						|
										const shortContentHashMap = {}; | 
						|
										const contentHash = chunkMaps.contentHash.javascript; | 
						|
										for (const chunkId of Object.keys(contentHash)) { | 
						|
											if (typeof contentHash[chunkId] === "string") { | 
						|
												shortContentHashMap[chunkId] = contentHash[ | 
						|
													chunkId | 
						|
												].substr(0, length); | 
						|
											} | 
						|
										} | 
						|
										return `" + ${JSON.stringify( | 
						|
											shortContentHashMap | 
						|
										)}[chunkId] + "`; | 
						|
									} | 
						|
								}, | 
						|
								name: `" + (${JSON.stringify( | 
						|
									chunkMaps.name | 
						|
								)}[chunkId]||chunkId) + "` | 
						|
							}, | 
						|
							contentHashType: "javascript" | 
						|
						} | 
						|
					); | 
						|
					return Template.asString([ | 
						|
						source, | 
						|
						"", | 
						|
						"// require() chunk loading for javascript", | 
						|
						"", | 
						|
						'// "0" is the signal for "already loaded"', | 
						|
						"if(installedChunks[chunkId] !== 0) {", | 
						|
						Template.indent( | 
						|
							[`var chunk = require(${request});`] | 
						|
								.concat(insertMoreModules) | 
						|
								.concat([ | 
						|
									"for(var i = 0; i < chunkIds.length; i++)", | 
						|
									Template.indent("installedChunks[chunkIds[i]] = 0;") | 
						|
								]) | 
						|
						), | 
						|
						"}" | 
						|
					]); | 
						|
				} | 
						|
			} | 
						|
		); | 
						|
		mainTemplate.hooks.hotBootstrap.tap( | 
						|
			"NodeMainTemplatePlugin", | 
						|
			(source, chunk, hash) => { | 
						|
				const hotUpdateChunkFilename = | 
						|
					mainTemplate.outputOptions.hotUpdateChunkFilename; | 
						|
				const hotUpdateMainFilename = | 
						|
					mainTemplate.outputOptions.hotUpdateMainFilename; | 
						|
				const chunkMaps = chunk.getChunkMaps(); | 
						|
				const currentHotUpdateChunkFilename = mainTemplate.getAssetPath( | 
						|
					JSON.stringify(hotUpdateChunkFilename), | 
						|
					{ | 
						|
						hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, | 
						|
						hashWithLength: length => | 
						|
							`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "`, | 
						|
						chunk: { | 
						|
							id: '" + chunkId + "', | 
						|
							hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, | 
						|
							hashWithLength: length => { | 
						|
								const shortChunkHashMap = {}; | 
						|
								for (const chunkId of Object.keys(chunkMaps.hash)) { | 
						|
									if (typeof chunkMaps.hash[chunkId] === "string") { | 
						|
										shortChunkHashMap[chunkId] = chunkMaps.hash[chunkId].substr( | 
						|
											0, | 
						|
											length | 
						|
										); | 
						|
									} | 
						|
								} | 
						|
								return `" + ${JSON.stringify(shortChunkHashMap)}[chunkId] + "`; | 
						|
							}, | 
						|
							name: `" + (${JSON.stringify( | 
						|
								chunkMaps.name | 
						|
							)}[chunkId]||chunkId) + "` | 
						|
						} | 
						|
					} | 
						|
				); | 
						|
				const currentHotUpdateMainFilename = mainTemplate.getAssetPath( | 
						|
					JSON.stringify(hotUpdateMainFilename), | 
						|
					{ | 
						|
						hash: `" + ${mainTemplate.renderCurrentHashCode(hash)} + "`, | 
						|
						hashWithLength: length => | 
						|
							`" + ${mainTemplate.renderCurrentHashCode(hash, length)} + "` | 
						|
					} | 
						|
				); | 
						|
				return Template.getFunctionContent( | 
						|
					asyncChunkLoading | 
						|
						? require("./NodeMainTemplateAsync.runtime") | 
						|
						: require("./NodeMainTemplate.runtime") | 
						|
				) | 
						|
					.replace(/\$require\$/g, mainTemplate.requireFn) | 
						|
					.replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename) | 
						|
					.replace(/\$hotChunkFilename\$/g, currentHotUpdateChunkFilename); | 
						|
			} | 
						|
		); | 
						|
		mainTemplate.hooks.hash.tap("NodeMainTemplatePlugin", hash => { | 
						|
			hash.update("node"); | 
						|
			hash.update("4"); | 
						|
		}); | 
						|
	} | 
						|
};
 | 
						|
 |