| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const RuntimeGlobals = require("../RuntimeGlobals"); | 
					
						
							|  |  |  | const RuntimeModule = require("../RuntimeModule"); | 
					
						
							|  |  |  | const Template = require("../Template"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-07 22:14:14 +08:00
										 |  |  | const createChunkNameExpr = obj => { | 
					
						
							|  |  |  | 	const optimizedObj = {}; | 
					
						
							|  |  |  | 	let hasEntries = false; | 
					
						
							|  |  |  | 	for (const key of Object.keys(obj)) { | 
					
						
							|  |  |  | 		const value = obj[key]; | 
					
						
							|  |  |  | 		if (key !== value) { | 
					
						
							|  |  |  | 			optimizedObj[key] = value; | 
					
						
							|  |  |  | 			hasEntries = true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return hasEntries | 
					
						
							|  |  |  | 		? `(${JSON.stringify(optimizedObj)}[chunkId]||chunkId)` | 
					
						
							|  |  |  | 		: "chunkId"; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | class GetChunkFilenameRuntimeModule extends RuntimeModule { | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 	constructor( | 
					
						
							|  |  |  | 		compilation, | 
					
						
							|  |  |  | 		chunk, | 
					
						
							|  |  |  | 		contentType, | 
					
						
							|  |  |  | 		name, | 
					
						
							|  |  |  | 		global, | 
					
						
							|  |  |  | 		filename, | 
					
						
							|  |  |  | 		getFilenameForChunk | 
					
						
							|  |  |  | 	) { | 
					
						
							| 
									
										
										
										
											2018-11-28 20:07:40 +08:00
										 |  |  | 		super(`get ${name} chunk filename`); | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 		this.compilation = compilation; | 
					
						
							|  |  |  | 		this.chunk = chunk; | 
					
						
							|  |  |  | 		this.contentType = contentType; | 
					
						
							|  |  |  | 		this.global = global; | 
					
						
							|  |  |  | 		this.filename = filename; | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 		this.getFilenameForChunk = getFilenameForChunk; | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							|  |  |  | 	 * @returns {string} runtime code | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	generate() { | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 		const { | 
					
						
							|  |  |  | 			global, | 
					
						
							|  |  |  | 			chunk, | 
					
						
							|  |  |  | 			contentType, | 
					
						
							|  |  |  | 			filename, | 
					
						
							|  |  |  | 			getFilenameForChunk, | 
					
						
							|  |  |  | 			compilation | 
					
						
							|  |  |  | 		} = this; | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 		const mainTemplate = compilation.mainTemplate; | 
					
						
							|  |  |  | 		const chunkMaps = chunk.getChunkMaps(); | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 		const staticUrls = new Map(); | 
					
						
							|  |  |  | 		const includeEntries = compilation.chunkGraph | 
					
						
							|  |  |  | 			.getTreeRuntimeRequirements(chunk) | 
					
						
							|  |  |  | 			.has(RuntimeGlobals.ensureChunkIncludeEntries); | 
					
						
							|  |  |  | 		if (includeEntries) { | 
					
						
							|  |  |  | 			for (const c of compilation.chunkGraph.getChunkEntryDependentChunksIterable( | 
					
						
							|  |  |  | 				chunk | 
					
						
							|  |  |  | 			)) { | 
					
						
							|  |  |  | 				const chunkFilename = getFilenameForChunk(c) || filename; | 
					
						
							|  |  |  | 				const staticChunkFilename = mainTemplate.getAssetPath( | 
					
						
							|  |  |  | 					JSON.stringify(chunkFilename), | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						hash: `" + ${RuntimeGlobals.getFullHash}() + "`, | 
					
						
							|  |  |  | 						chunk: c, | 
					
						
							|  |  |  | 						contentHashType: contentType | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 				// TODO optimize this to not include static filenames when it could be generated by the templated expression
 | 
					
						
							|  |  |  | 				staticUrls.set(c.id, staticChunkFilename); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 		const url = mainTemplate.getAssetPath(JSON.stringify(filename), { | 
					
						
							|  |  |  | 			hash: `" + ${RuntimeGlobals.getFullHash}() + "`, | 
					
						
							|  |  |  | 			hashWithLength: length => | 
					
						
							|  |  |  | 				`" + ${RuntimeGlobals.getFullHash}().slice(0, ${length}) + "`, | 
					
						
							|  |  |  | 			chunk: { | 
					
						
							|  |  |  | 				id: `" + chunkId + "`, | 
					
						
							|  |  |  | 				hash: `" + ${JSON.stringify(chunkMaps.hash)}[chunkId] + "`, | 
					
						
							|  |  |  | 				hashWithLength(length) { | 
					
						
							|  |  |  | 					const shortChunkHashMap = Object.create(null); | 
					
						
							|  |  |  | 					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] + "`; | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2018-12-07 22:14:14 +08:00
										 |  |  | 				name: `" + ${createChunkNameExpr(chunkMaps.name)} + "`, | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 				contentHash: { | 
					
						
							|  |  |  | 					[contentType]: `" + ${JSON.stringify( | 
					
						
							|  |  |  | 						chunkMaps.contentHash[contentType] | 
					
						
							|  |  |  | 					)}[chunkId] + "`
 | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 				contentHashWithLength: { | 
					
						
							|  |  |  | 					[contentType]: length => { | 
					
						
							|  |  |  | 						const shortContentHashMap = {}; | 
					
						
							|  |  |  | 						const contentHash = chunkMaps.contentHash[contentType]; | 
					
						
							| 
									
										
										
										
											2018-11-23 16:37:33 +08:00
										 |  |  | 						if (!contentHash) return "XXXX"; | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 						for (const chunkId of Object.keys(contentHash)) { | 
					
						
							|  |  |  | 							if (typeof contentHash[chunkId] === "string") { | 
					
						
							|  |  |  | 								shortContentHashMap[chunkId] = contentHash[chunkId].substr( | 
					
						
							|  |  |  | 									0, | 
					
						
							|  |  |  | 									length | 
					
						
							|  |  |  | 								); | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 						return `" + ${JSON.stringify(shortContentHashMap)}[chunkId] + "`; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			contentHashType: contentType | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 		return Template.asString([ | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 			staticUrls.size > 16 | 
					
						
							|  |  |  | 				? Template.asString([ | 
					
						
							|  |  |  | 						"// mapping for filenames not based on template", | 
					
						
							|  |  |  | 						`var staticMapping = ${JSON.stringify( | 
					
						
							|  |  |  | 							Array.from(staticUrls).reduce( | 
					
						
							|  |  |  | 								(obj, [key, value]) => ((obj[key] = value), obj), | 
					
						
							|  |  |  | 								{} | 
					
						
							|  |  |  | 							), | 
					
						
							|  |  |  | 							null, | 
					
						
							|  |  |  | 							"\t" | 
					
						
							|  |  |  | 						)};`
 | 
					
						
							|  |  |  | 				  ]) | 
					
						
							|  |  |  | 				: "", | 
					
						
							|  |  |  | 			includeEntries | 
					
						
							|  |  |  | 				? "// This function also allow to reference entries" | 
					
						
							|  |  |  | 				: "// This function only allows to reference on-demand chunks", | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 			`${global} = function(chunkId) {`, | 
					
						
							| 
									
										
										
										
											2018-12-29 19:48:59 +08:00
										 |  |  | 			Template.indent( | 
					
						
							|  |  |  | 				staticUrls.size > 16 | 
					
						
							|  |  |  | 					? [ | 
					
						
							|  |  |  | 							// object is shorter for 16 or more cases
 | 
					
						
							|  |  |  | 							"// return url for filenames either based on template or not", | 
					
						
							|  |  |  | 							`return Object.prototype.hasOwnProperty.call(staticMapping, chunkId) ? staticMapping[chunkId] : ${url};` | 
					
						
							|  |  |  | 					  ] | 
					
						
							|  |  |  | 					: staticUrls.size > 0 | 
					
						
							|  |  |  | 						? [ | 
					
						
							|  |  |  | 								// if is shorter for 1 - 15 cases
 | 
					
						
							|  |  |  | 								// it minimizes to `x===1?"...":x===2?"...":"..."`
 | 
					
						
							|  |  |  | 								"// return url for filenames not based on template", | 
					
						
							|  |  |  | 								Template.asString( | 
					
						
							|  |  |  | 									Array.from(staticUrls).map( | 
					
						
							|  |  |  | 										([id, url]) => | 
					
						
							|  |  |  | 											`if(chunkId === ${JSON.stringify(id)}) return ${url};` | 
					
						
							|  |  |  | 									) | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 								"// return url for filenames based on template", | 
					
						
							|  |  |  | 								`return ${url};` | 
					
						
							|  |  |  | 						  ] | 
					
						
							|  |  |  | 						: [ | 
					
						
							|  |  |  | 								"// return url for filenames based on template", | 
					
						
							|  |  |  | 								`return ${url};` | 
					
						
							|  |  |  | 						  ] | 
					
						
							|  |  |  | 			), | 
					
						
							| 
									
										
										
										
											2018-11-21 18:32:10 +08:00
										 |  |  | 			"};" | 
					
						
							|  |  |  | 		]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = GetChunkFilenameRuntimeModule; |