Merge pull request #5312 from webpack/performance/aggressive-splitting

performance improvements and comments
This commit is contained in:
Tobias Koppers 2017-07-18 15:11:24 +02:00 committed by GitHub
commit 2b0943f618
1 changed files with 44 additions and 31 deletions

View File

@ -39,6 +39,13 @@ class AggressiveSplittingPlugin {
apply(compiler) {
compiler.plugin("this-compilation", (compilation) => {
compilation.plugin("optimize-chunks-advanced", (chunks) => {
// Precompute stuff
const nameToModuleMap = new Map();
compilation.modules.forEach(m => {
const name = identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache);
nameToModuleMap.set(name, m);
});
const savedSplits = compilation.records && compilation.records.aggressiveSplits || [];
const usedSplits = compilation._aggressiveSplittingSplits ?
savedSplits.concat(compilation._aggressiveSplittingSplits) : savedSplits;
@ -48,45 +55,51 @@ class AggressiveSplittingPlugin {
// 1. try to restore to recorded splitting
for(let j = 0; j < usedSplits.length; j++) {
const splitData = usedSplits[j];
for(let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
const selectedModules = splitData.modules.map(name => nameToModuleMap.get(name));
if(chunk.getNumberOfModules() < splitData.modules.length)
continue;
// Does the modules exist at all?
if(selectedModules.every(Boolean)) {
const nameToModuleMap = new Map();
chunk.forEachModule(m => {
const name = identifierUtils.makePathsRelative(compiler.context, m.identifier(), compilation.cache);
nameToModuleMap.set(name, m);
});
// Find all chunks containing all modules in the split
for(let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
const selectedModules = splitData.modules.map(name => nameToModuleMap.get(name));
if(selectedModules.every(Boolean)) {
if(chunk.getNumberOfModules() > splitData.modules.length) {
const newChunk = compilation.addChunk();
selectedModules.forEach(moveModuleBetween(chunk, newChunk));
chunk.split(newChunk);
chunk.name = null;
newChunk._fromAggressiveSplitting = true;
if(j < savedSplits.length)
newChunk._fromAggressiveSplittingIndex = j;
if(splitData.id !== null && splitData.id !== undefined) {
newChunk.id = splitData.id;
}
newChunk.origins = chunk.origins.map(copyWithReason);
chunk.origins = chunk.origins.map(copyWithReason);
return true;
} else {
if(j < savedSplits.length)
chunk._fromAggressiveSplittingIndex = j;
chunk.name = null;
if(splitData.id !== null && splitData.id !== undefined) {
chunk.id = splitData.id;
// Cheap check if chunk is suitable at all
if(chunk.getNumberOfModules() < splitData.modules.length)
continue;
// Check if all modules are in the chunk
if(selectedModules.every(m => chunk.containsModule(m))) {
// Is chunk identical to the split or do we need to split it?
if(chunk.getNumberOfModules() > splitData.modules.length) {
// split the chunk into two parts
const newChunk = compilation.addChunk();
selectedModules.forEach(moveModuleBetween(chunk, newChunk));
chunk.split(newChunk);
chunk.name = null;
newChunk._fromAggressiveSplitting = true;
if(j < savedSplits.length)
newChunk._fromAggressiveSplittingIndex = j;
if(splitData.id !== null && splitData.id !== undefined) {
newChunk.id = splitData.id;
}
newChunk.origins = chunk.origins.map(copyWithReason);
chunk.origins = chunk.origins.map(copyWithReason);
return true;
} else { // chunk is identical to the split
if(j < savedSplits.length)
chunk._fromAggressiveSplittingIndex = j;
chunk.name = null;
if(splitData.id !== null && splitData.id !== undefined) {
chunk.id = splitData.id;
}
}
}
}
}
}
// 2. for any other chunk which isn't splitted yet, split it
for(let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];