Smaller performance improvements in NormalModuleFactory

This commit is contained in:
Tobias Koppers 2019-01-05 11:19:30 +01:00
parent 526bc7a788
commit 90baf475af
3 changed files with 279 additions and 240 deletions

View File

@ -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 is nested so we need to allow one additional task
this.processDependenciesQueue.increaseParallelism(); this.processDependenciesQueue.increaseParallelism();
@ -839,6 +845,7 @@ class Compilation {
return callback(err); return callback(err);
} }
); );
});
} }
/** /**

View File

@ -566,6 +566,7 @@ class Compiler {
this.hooks.make.callAsync(compilation, err => { this.hooks.make.callAsync(compilation, err => {
if (err) return callback(err); if (err) return callback(err);
process.nextTick(() => {
compilation.finish(err => { compilation.finish(err => {
if (err) return callback(err); if (err) return callback(err);
@ -581,6 +582,7 @@ class Compiler {
}); });
}); });
}); });
});
} }
/** /**

View File

@ -58,6 +58,14 @@ const loaderToIdent = data => {
return data.loader + "?" + JSON.stringify(data.options); 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 identToLoaderRequest = resultString => {
const idx = resultString.indexOf("?"); const idx = resultString.indexOf("?");
if (idx >= 0) { 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 // TODO webpack 6 remove
const deprecationChangedHookMessage = name => const deprecationChangedHookMessage = name =>
`NormalModuleFactory.${name} is no longer a waterfall hook, but a bailing hook instead. ` + `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); const matchResourceMatch = MATCH_RESOURCE_REGEX.exec(request);
if (matchResourceMatch) { if (matchResourceMatch) {
matchResource = matchResourceMatch[1]; 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); matchResource = path.join(context, matchResource);
} }
}
requestWithoutMatchResource = request.substr( requestWithoutMatchResource = request.substr(
matchResourceMatch[0].length matchResourceMatch[0].length
); );
} }
const noPreAutoLoaders = requestWithoutMatchResource.startsWith("-!"); const firstChar = requestWithoutMatchResource.charCodeAt(0);
const noAutoLoaders = const secondChar = requestWithoutMatchResource.charCodeAt(1);
noPreAutoLoaders || requestWithoutMatchResource.startsWith("!"); const noPreAutoLoaders = firstChar === 45 && secondChar === 33; // startsWith "-!"
const noPrePostAutoLoaders = requestWithoutMatchResource.startsWith( const noAutoLoaders = noPreAutoLoaders || firstChar === 33; // startsWith "!"
"!!" const noPrePostAutoLoaders = firstChar === 33 && secondChar === 33; // startsWith "!!";
);
const rawElements = requestWithoutMatchResource const rawElements = requestWithoutMatchResource
.replace(/^-?!+/, "") .slice(
.replace(/!!+/g, "!") noPreAutoLoaders || noPrePostAutoLoaders ? 2 : noAutoLoaders ? 1 : 0
.split("!"); )
const resource = rawElements.pop(); .split(/!+/);
const unresolvedResource = rawElements.pop();
const elements = rawElements.map(identToLoaderRequest); const elements = rawElements.map(identToLoaderRequest);
const resolveContext = { const resolveContext = {
@ -224,58 +252,18 @@ class NormalModuleFactory extends ModuleFactory {
contextDependencies contextDependencies
}; };
asyncLib.parallel( /** @type {string | false} */
[ let resource;
callback => let resourceResolveData;
this.resolveRequestArray( let loaders;
contextInfo,
context,
elements,
loaderResolver,
resolveContext,
callback
),
callback => {
if (resource === "" || resource[0] === "?") {
return callback(null, {
resource
});
}
normalResolver.resolve( const continueCallback = needCalls(2, err => {
contextInfo,
context,
resource,
resolveContext,
(err, resource, resourceResolveData) => {
if (err) return callback(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 // translate option idents
try { try {
for (const item of loaders) { for (const item of loaders) {
if ( if (typeof item.options === "string" && item.options[0] === "?") {
typeof item.options === "string" &&
item.options[0] === "?"
) {
const ident = item.options.substr(1); const ident = item.options.substr(1);
item.options = this.ruleSet.findOptionsByIdent(ident); item.options = this.ruleSet.findOptionsByIdent(ident);
item.ident = ident; item.ident = ident;
@ -299,10 +287,7 @@ class NormalModuleFactory extends ModuleFactory {
const userRequest = const userRequest =
(matchResource !== undefined ? `${matchResource}!=!` : "") + (matchResource !== undefined ? `${matchResource}!=!` : "") +
loaders stringifyLoadersAndResource(loaders, resource);
.map(loaderToIdent)
.concat([resource])
.join("!");
let resourcePath = let resourcePath =
matchResource !== undefined ? matchResource : resource; matchResource !== undefined ? matchResource : resource;
@ -355,48 +340,24 @@ class NormalModuleFactory extends ModuleFactory {
settings[r.type] = r.value; settings[r.type] = r.value;
} }
} }
asyncLib.parallel(
[ let postLoaders, normalLoaders, preLoaders;
this.resolveRequestArray.bind(
this, const continueCallback = needCalls(3, err => {
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) => {
if (err) { if (err) {
return callback(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 type = settings.type;
const resolveOptions = settings.resolve; const resolveOptions = settings.resolve;
Object.assign(data.createData, { Object.assign(data.createData, {
request: loaders request: stringifyLoadersAndResource(allLoaders, resource),
.map(loaderToIdent)
.concat([resource])
.join("!"),
userRequest, userRequest,
rawRequest: request, rawRequest: request,
loaders, loaders: allLoaders,
resource, resource,
matchResource, matchResource,
resourceResolveData, resourceResolveData,
@ -407,8 +368,80 @@ class NormalModuleFactory extends ModuleFactory {
resolveOptions resolveOptions
}); });
callback(); 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, resolveContext,
callback callback
) { ) {
if (array.length === 0) return callback(null, []); if (array.length === 0) return callback(null, array);
asyncLib.map( asyncLib.map(
array, array,
(item, callback) => { (item, callback) => {
@ -503,7 +536,7 @@ class NormalModuleFactory extends ModuleFactory {
contextInfo, contextInfo,
context, context,
item.loader + "-loader", item.loader + "-loader",
{}, resolveContext,
err2 => { err2 => {
if (!err2) { if (!err2) {
err.message = err.message =
@ -521,18 +554,15 @@ class NormalModuleFactory extends ModuleFactory {
} }
if (err) return callback(err); if (err) return callback(err);
const optionsOnly = item.options const parsedResult = identToLoaderRequest(result);
? { const resolved = {
options: item.options loader: parsedResult.loader,
} options:
: undefined; item.options === undefined
? parsedResult.options
const resolved = Object.assign( : item.options,
{}, ident: item.options === undefined ? undefined : item.ident
item, };
identToLoaderRequest(result),
optionsOnly
);
// TODO remove this when enhanced-resolve supports fileDependencies // TODO remove this when enhanced-resolve supports fileDependencies
if (resolved.loader) { if (resolved.loader) {