mirror of https://github.com/webpack/webpack.git
				
				
				
			Smaller performance improvements in NormalModuleFactory
This commit is contained in:
		
							parent
							
								
									526bc7a788
								
							
						
					
					
						commit
						90baf475af
					
				|  | @ -808,6 +808,12 @@ class Compilation { | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (sortedDependencies.length === 0) { | ||||
| 			callback(); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		process.nextTick(() => { | ||||
| 			// This is nested so we need to allow one additional task
 | ||||
| 			this.processDependenciesQueue.increaseParallelism(); | ||||
| 
 | ||||
|  | @ -839,6 +845,7 @@ class Compilation { | |||
| 					return callback(err); | ||||
| 				} | ||||
| 			); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -566,6 +566,7 @@ class Compiler { | |||
| 			this.hooks.make.callAsync(compilation, err => { | ||||
| 				if (err) return callback(err); | ||||
| 
 | ||||
| 				process.nextTick(() => { | ||||
| 					compilation.finish(err => { | ||||
| 						if (err) return callback(err); | ||||
| 
 | ||||
|  | @ -581,6 +582,7 @@ class Compiler { | |||
| 					}); | ||||
| 				}); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  |  | |||
|  | @ -58,6 +58,14 @@ const loaderToIdent = data => { | |||
| 	return data.loader + "?" + JSON.stringify(data.options); | ||||
| }; | ||||
| 
 | ||||
| const stringifyLoadersAndResource = (loaders, resource) => { | ||||
| 	let str = ""; | ||||
| 	for (const loader of loaders) { | ||||
| 		str += loaderToIdent(loader) + "!"; | ||||
| 	} | ||||
| 	return str + resource; | ||||
| }; | ||||
| 
 | ||||
| const identToLoaderRequest = resultString => { | ||||
| 	const idx = resultString.indexOf("?"); | ||||
| 	if (idx >= 0) { | ||||
|  | @ -75,6 +83,18 @@ const identToLoaderRequest = resultString => { | |||
| 	} | ||||
| }; | ||||
| 
 | ||||
| const needCalls = (times, callback) => { | ||||
| 	return err => { | ||||
| 		if (--times === 0) { | ||||
| 			return callback(err); | ||||
| 		} | ||||
| 		if (err && times > 0) { | ||||
| 			times = NaN; | ||||
| 			return callback(err); | ||||
| 		} | ||||
| 	}; | ||||
| }; | ||||
| 
 | ||||
| // TODO webpack 6 remove
 | ||||
| const deprecationChangedHookMessage = name => | ||||
| 	`NormalModuleFactory.${name} is no longer a waterfall hook, but a bailing hook instead. ` + | ||||
|  | @ -196,25 +216,33 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 				const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request); | ||||
| 				if (matchResourceMatch) { | ||||
| 					matchResource = matchResourceMatch[1]; | ||||
| 					if (/^\.\.?\//.test(matchResource)) { | ||||
| 					if (matchResource.charCodeAt(0) === 46) { | ||||
| 						// 46 === ".", 47 === "/"
 | ||||
| 						const secondChar = matchResource.charCodeAt(1); | ||||
| 						if ( | ||||
| 							secondChar === 47 || | ||||
| 							(secondChar === 46 && matchResource.charCodeAt(2) === 47) | ||||
| 						) { | ||||
| 							// if matchResources startsWith ../ or ./
 | ||||
| 							matchResource = path.join(context, matchResource); | ||||
| 						} | ||||
| 					} | ||||
| 					requestWithoutMatchResource = request.substr( | ||||
| 						matchResourceMatch[0].length | ||||
| 					); | ||||
| 				} | ||||
| 
 | ||||
| 				const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!"); | ||||
| 				const noAutoLoaders = | ||||
| 					noPreAutoLoaders || requestWithoutMatchResource.startsWith("!"); | ||||
| 				const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith( | ||||
| 					"!!" | ||||
| 				); | ||||
| 				const firstChar = requestWithoutMatchResource.charCodeAt(0); | ||||
| 				const secondChar = requestWithoutMatchResource.charCodeAt(1); | ||||
| 				const noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
 | ||||
| 				const noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
 | ||||
| 				const noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
 | ||||
| 				const rawElements = requestWithoutMatchResource | ||||
| 					.replace(/^-?!+/, "") | ||||
| 					.replace(/!!+/g, "!") | ||||
| 					.split("!"); | ||||
| 				const resource = rawElements.pop(); | ||||
| 					.slice( | ||||
| 						noPreAutoLoaders || noPrePostAutoLoaders ? 2 : noAutoLoaders ? 1 : 0 | ||||
| 					) | ||||
| 					.split(/!+/); | ||||
| 				const unresolvedResource = rawElements.pop(); | ||||
| 				const elements = rawElements.map(identToLoaderRequest); | ||||
| 
 | ||||
| 				const resolveContext = { | ||||
|  | @ -224,58 +252,18 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 					contextDependencies | ||||
| 				}; | ||||
| 
 | ||||
| 				asyncLib.parallel( | ||||
| 					[ | ||||
| 						callback => | ||||
| 							this.resolveRequestArray( | ||||
| 								contextInfo, | ||||
| 								context, | ||||
| 								elements, | ||||
| 								loaderResolver, | ||||
| 								resolveContext, | ||||
| 								callback | ||||
| 							), | ||||
| 						callback => { | ||||
| 							if (resource === "" || resource[0] === "?") { | ||||
| 								return callback(null, { | ||||
| 									resource | ||||
| 								}); | ||||
| 							} | ||||
| 				/** @type {string | false} */ | ||||
| 				let resource; | ||||
| 				let resourceResolveData; | ||||
| 				let loaders; | ||||
| 
 | ||||
| 							normalResolver.resolve( | ||||
| 								contextInfo, | ||||
| 								context, | ||||
| 								resource, | ||||
| 								resolveContext, | ||||
| 								(err, resource, resourceResolveData) => { | ||||
| 				const continueCallback = needCalls(2, err => { | ||||
| 					if (err) return callback(err); | ||||
| 
 | ||||
| 									// TODO remove this when enhanced-resolve supports fileDependencies
 | ||||
| 									if (resource) { | ||||
| 										fileDependencies.add(resource); | ||||
| 									} | ||||
| 
 | ||||
| 									callback(null, { | ||||
| 										resourceResolveData, | ||||
| 										resource | ||||
| 									}); | ||||
| 								} | ||||
| 							); | ||||
| 						} | ||||
| 					], | ||||
| 					(err, results) => { | ||||
| 						if (err) return callback(err); | ||||
| 						let loaders = results[0]; | ||||
| 						const resourceResolveData = results[1].resourceResolveData; | ||||
| 						const resource = results[1].resource; | ||||
| 
 | ||||
| 					// translate option idents
 | ||||
| 					try { | ||||
| 						for (const item of loaders) { | ||||
| 								if ( | ||||
| 									typeof item.options === "string" && | ||||
| 									item.options[0] === "?" | ||||
| 								) { | ||||
| 							if (typeof item.options === "string" && item.options[0] === "?") { | ||||
| 								const ident = item.options.substr(1); | ||||
| 								item.options = this.ruleSet.findOptionsByIdent(ident); | ||||
| 								item.ident = ident; | ||||
|  | @ -299,10 +287,7 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 
 | ||||
| 					const userRequest = | ||||
| 						(matchResource !== undefined ? `${matchResource}!=!` : "") + | ||||
| 							loaders | ||||
| 								.map(loaderToIdent) | ||||
| 								.concat([resource]) | ||||
| 								.join("!"); | ||||
| 						stringifyLoadersAndResource(loaders, resource); | ||||
| 
 | ||||
| 					let resourcePath = | ||||
| 						matchResource !== undefined ? matchResource : resource; | ||||
|  | @ -355,48 +340,24 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 							settings[r.type] = r.value; | ||||
| 						} | ||||
| 					} | ||||
| 						asyncLib.parallel( | ||||
| 							[ | ||||
| 								this.resolveRequestArray.bind( | ||||
| 									this, | ||||
| 									contextInfo, | ||||
| 									this.context, | ||||
| 									useLoadersPost, | ||||
| 									loaderResolver, | ||||
| 									resolveContext | ||||
| 								), | ||||
| 								this.resolveRequestArray.bind( | ||||
| 									this, | ||||
| 									contextInfo, | ||||
| 									this.context, | ||||
| 									useLoaders, | ||||
| 									loaderResolver, | ||||
| 									resolveContext | ||||
| 								), | ||||
| 								this.resolveRequestArray.bind( | ||||
| 									this, | ||||
| 									contextInfo, | ||||
| 									this.context, | ||||
| 									useLoadersPre, | ||||
| 									loaderResolver, | ||||
| 									resolveContext | ||||
| 								) | ||||
| 							], | ||||
| 							(err, results) => { | ||||
| 
 | ||||
| 					let postLoaders, normalLoaders, preLoaders; | ||||
| 
 | ||||
| 					const continueCallback = needCalls(3, err => { | ||||
| 						if (err) { | ||||
| 							return callback(err); | ||||
| 						} | ||||
| 								loaders = results[0].concat(loaders, results[1], results[2]); | ||||
| 						const allLoaders = postLoaders; | ||||
| 						for (const loader of loaders) allLoaders.push(loader); | ||||
| 						for (const loader of normalLoaders) allLoaders.push(loader); | ||||
| 						for (const loader of preLoaders) allLoaders.push(loader); | ||||
| 						const type = settings.type; | ||||
| 						const resolveOptions = settings.resolve; | ||||
| 						Object.assign(data.createData, { | ||||
| 									request: loaders | ||||
| 										.map(loaderToIdent) | ||||
| 										.concat([resource]) | ||||
| 										.join("!"), | ||||
| 							request: stringifyLoadersAndResource(allLoaders, resource), | ||||
| 							userRequest, | ||||
| 							rawRequest: request, | ||||
| 									loaders, | ||||
| 							loaders: allLoaders, | ||||
| 							resource, | ||||
| 							matchResource, | ||||
| 							resourceResolveData, | ||||
|  | @ -407,8 +368,80 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 							resolveOptions | ||||
| 						}); | ||||
| 						callback(); | ||||
| 					}); | ||||
| 					this.resolveRequestArray( | ||||
| 						contextInfo, | ||||
| 						this.context, | ||||
| 						useLoadersPost, | ||||
| 						loaderResolver, | ||||
| 						resolveContext, | ||||
| 						(err, result) => { | ||||
| 							postLoaders = result; | ||||
| 							continueCallback(err); | ||||
| 						} | ||||
| 					); | ||||
| 					this.resolveRequestArray( | ||||
| 						contextInfo, | ||||
| 						this.context, | ||||
| 						useLoaders, | ||||
| 						loaderResolver, | ||||
| 						resolveContext, | ||||
| 						(err, result) => { | ||||
| 							normalLoaders = result; | ||||
| 							continueCallback(err); | ||||
| 						} | ||||
| 					); | ||||
| 					this.resolveRequestArray( | ||||
| 						contextInfo, | ||||
| 						this.context, | ||||
| 						useLoadersPre, | ||||
| 						loaderResolver, | ||||
| 						resolveContext, | ||||
| 						(err, result) => { | ||||
| 							preLoaders = result; | ||||
| 							continueCallback(err); | ||||
| 						} | ||||
| 					); | ||||
| 				}); | ||||
| 
 | ||||
| 				this.resolveRequestArray( | ||||
| 					contextInfo, | ||||
| 					context, | ||||
| 					elements, | ||||
| 					loaderResolver, | ||||
| 					resolveContext, | ||||
| 					(err, result) => { | ||||
| 						if (err) return continueCallback(err); | ||||
| 						loaders = result; | ||||
| 						continueCallback(); | ||||
| 					} | ||||
| 				); | ||||
| 
 | ||||
| 				if ( | ||||
| 					unresolvedResource === "" || | ||||
| 					unresolvedResource.charCodeAt(0) === 63 | ||||
| 				) { | ||||
| 					// 63 === "?"
 | ||||
| 					resource = unresolvedResource; | ||||
| 					return continueCallback(); | ||||
| 				} | ||||
| 
 | ||||
| 				normalResolver.resolve( | ||||
| 					contextInfo, | ||||
| 					context, | ||||
| 					unresolvedResource, | ||||
| 					resolveContext, | ||||
| 					(err, resolvedResource, resolvedResourceResolveData) => { | ||||
| 						if (err) return continueCallback(err); | ||||
| 
 | ||||
| 						// TODO remove this when enhanced-resolve supports fileDependencies
 | ||||
| 						if (resolvedResource) { | ||||
| 							fileDependencies.add(resolvedResource); | ||||
| 						} | ||||
| 
 | ||||
| 						resource = resolvedResource; | ||||
| 						resourceResolveData = resolvedResourceResolveData; | ||||
| 						continueCallback(); | ||||
| 					} | ||||
| 				); | ||||
| 			} | ||||
|  | @ -484,7 +517,7 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 		resolveContext, | ||||
| 		callback | ||||
| 	) { | ||||
| 		if (array.length === 0) return callback(null, []); | ||||
| 		if (array.length === 0) return callback(null, array); | ||||
| 		asyncLib.map( | ||||
| 			array, | ||||
| 			(item, callback) => { | ||||
|  | @ -503,7 +536,7 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 								contextInfo, | ||||
| 								context, | ||||
| 								item.loader + "-loader", | ||||
| 								{}, | ||||
| 								resolveContext, | ||||
| 								err2 => { | ||||
| 									if (!err2) { | ||||
| 										err.message = | ||||
|  | @ -521,18 +554,15 @@ class NormalModuleFactory extends ModuleFactory { | |||
| 						} | ||||
| 						if (err) return callback(err); | ||||
| 
 | ||||
| 						const optionsOnly = item.options | ||||
| 							? { | ||||
| 									options: item.options | ||||
| 							  } | ||||
| 							: undefined; | ||||
| 
 | ||||
| 						const resolved = Object.assign( | ||||
| 							{}, | ||||
| 							item, | ||||
| 							identToLoaderRequest(result), | ||||
| 							optionsOnly | ||||
| 						); | ||||
| 						const parsedResult = identToLoaderRequest(result); | ||||
| 						const resolved = { | ||||
| 							loader: parsedResult.loader, | ||||
| 							options: | ||||
| 								item.options === undefined | ||||
| 									? parsedResult.options | ||||
| 									: item.options, | ||||
| 							ident: item.options === undefined ? undefined : item.ident | ||||
| 						}; | ||||
| 
 | ||||
| 						// TODO remove this when enhanced-resolve supports fileDependencies
 | ||||
| 						if (resolved.loader) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue