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