Replace Basic and Advanced optimzation hooks by stages

This commit is contained in:
Florent Cailhol 2018-07-30 22:30:27 +02:00 committed by Tobias Koppers
parent a6e1c0693c
commit 7b02084bc5
18 changed files with 129 additions and 92 deletions

View File

@ -220,32 +220,20 @@ class Compilation {
/** @type {SyncHook<Chunk[]>} */
afterChunks: new SyncHook(["chunks"]),
/** @type {SyncBailHook<Module[]>} */
optimizeDependenciesBasic: new SyncBailHook(["modules"]),
/** @type {SyncBailHook<Module[]>} */
optimizeDependencies: new SyncBailHook(["modules"]),
/** @type {SyncBailHook<Module[]>} */
optimizeDependenciesAdvanced: new SyncBailHook(["modules"]),
/** @type {SyncBailHook<Module[]>} */
afterOptimizeDependencies: new SyncHook(["modules"]),
/** @type {SyncHook} */
optimize: new SyncHook([]),
/** @type {SyncBailHook<Module[]>} */
optimizeModulesBasic: new SyncBailHook(["modules"]),
/** @type {SyncBailHook<Module[]>} */
optimizeModules: new SyncBailHook(["modules"]),
/** @type {SyncBailHook<Module[]>} */
optimizeModulesAdvanced: new SyncBailHook(["modules"]),
/** @type {SyncHook<Module[]>} */
afterOptimizeModules: new SyncHook(["modules"]),
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
optimizeChunksBasic: new SyncBailHook(["chunks", "chunkGroups"]),
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
/** @type {SyncBailHook<Chunk[], ChunkGroup[]>} */
optimizeChunksAdvanced: new SyncBailHook(["chunks", "chunkGroups"]),
/** @type {SyncHook<Chunk[], ChunkGroup[]>} */
afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
@ -254,12 +242,8 @@ class Compilation {
/** @type {SyncHook<Chunk[], Module[]>} */
afterOptimizeTree: new SyncHook(["chunks", "modules"]),
/** @type {SyncBailHook<Chunk[], Module[]>} */
optimizeChunkModulesBasic: new SyncBailHook(["chunks", "modules"]),
/** @type {SyncBailHook<Chunk[], Module[]>} */
optimizeChunkModules: new SyncBailHook(["chunks", "modules"]),
/** @type {SyncBailHook<Chunk[], Module[]>} */
optimizeChunkModulesAdvanced: new SyncBailHook(["chunks", "modules"]),
/** @type {SyncHook<Chunk[], Module[]>} */
afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
/** @type {SyncBailHook} */
@ -1098,11 +1082,7 @@ class Compilation {
this.hooks.seal.call();
while (
this.hooks.optimizeDependenciesBasic.call(this.modules) ||
this.hooks.optimizeDependencies.call(this.modules) ||
this.hooks.optimizeDependenciesAdvanced.call(this.modules)
) {
while (this.hooks.optimizeDependencies.call(this.modules)) {
/* empty */
}
this.hooks.afterOptimizeDependencies.call(this.modules);
@ -1135,20 +1115,12 @@ class Compilation {
this.hooks.optimize.call();
while (
this.hooks.optimizeModulesBasic.call(this.modules) ||
this.hooks.optimizeModules.call(this.modules) ||
this.hooks.optimizeModulesAdvanced.call(this.modules)
) {
while (this.hooks.optimizeModules.call(this.modules)) {
/* empty */
}
this.hooks.afterOptimizeModules.call(this.modules);
while (
this.hooks.optimizeChunksBasic.call(this.chunks, this.chunkGroups) ||
this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups) ||
this.hooks.optimizeChunksAdvanced.call(this.chunks, this.chunkGroups)
) {
while (this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups)) {
/* empty */
}
this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups);
@ -1160,11 +1132,7 @@ class Compilation {
this.hooks.afterOptimizeTree.call(this.chunks, this.modules);
while (
this.hooks.optimizeChunkModulesBasic.call(this.chunks, this.modules) ||
this.hooks.optimizeChunkModules.call(this.chunks, this.modules) ||
this.hooks.optimizeChunkModulesAdvanced.call(this.chunks, this.modules)
) {
while (this.hooks.optimizeChunkModules.call(this.chunks, this.modules)) {
/* empty */
}
this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules);

View File

@ -5,6 +5,7 @@
"use strict";
const { STAGE_DEFAULT } = require("./OptimizationStages");
const SortableSet = require("./util/SortableSet");
/** @typedef {import("./Compiler")} Compiler */
@ -38,7 +39,10 @@ class FlagDependencyUsagePlugin {
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
const moduleGraph = compilation.moduleGraph;
compilation.hooks.optimizeDependencies.tap(
"FlagDependencyUsagePlugin",
/** @type {TODO} */ ({
name: "FlagDependencyUsagePlugin",
stage: STAGE_DEFAULT
}),
modules => {
/**
*

10
lib/OptimizationStages.js Normal file
View File

@ -0,0 +1,10 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Florent Cailhol @ooflorent
*/
"use strict";
exports.STAGE_BASIC = 0;
exports.STAGE_DEFAULT = 10;
exports.STAGE_ADVANCED = 20;

View File

@ -138,24 +138,16 @@ class ProgressPlugin {
const hooks = {
finishModules: "finish module graph",
seal: "sealing",
optimizeDependenciesBasic: "basic dependencies optimization",
optimizeDependencies: "dependencies optimization",
optimizeDependenciesAdvanced: "advanced dependencies optimization",
afterOptimizeDependencies: "after dependencies optimization",
optimize: "optimizing",
optimizeModulesBasic: "basic module optimization",
optimizeModules: "module optimization",
optimizeModulesAdvanced: "advanced module optimization",
afterOptimizeModules: "after module optimization",
optimizeChunksBasic: "basic chunk optimization",
optimizeChunks: "chunk optimization",
optimizeChunksAdvanced: "advanced chunk optimization",
afterOptimizeChunks: "after chunk optimization",
optimizeTree: "module and chunk tree optimization",
afterOptimizeTree: "after module and chunk tree optimization",
optimizeChunkModulesBasic: "basic chunk modules optimization",
optimizeChunkModules: "chunk modules optimization",
optimizeChunkModulesAdvanced: "advanced chunk modules optimization",
afterOptimizeChunkModules: "after chunk modules optimization",
reviveModules: "module reviving",
optimizeModuleOrder: "module order optimization",

View File

@ -5,6 +5,8 @@
"use strict";
const { STAGE_ADVANCED } = require("../OptimizationStages");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
@ -32,8 +34,11 @@ class AggressiveMergingPlugin {
compiler.hooks.thisCompilation.tap(
"AggressiveMergingPlugin",
compilation => {
compilation.hooks.optimizeChunksAdvanced.tap(
"AggressiveMergingPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "AggressiveMergingPlugin",
stage: STAGE_ADVANCED
}),
chunks => {
const chunkGraph = compilation.chunkGraph;
/** @type {{a: Chunk, b: Chunk, improvement: number}[]} */

View File

@ -7,6 +7,7 @@
const validateOptions = require("schema-utils");
const schema = require("../../schemas/plugins/optimize/AggressiveSplittingPlugin.json");
const { STAGE_ADVANCED } = require("../OptimizationStages");
const { intersect } = require("../util/SetHelpers");
const { compareModulesById } = require("../util/comparators");
const identifierUtils = require("../util/identifier");
@ -81,8 +82,11 @@ class AggressiveSplittingPlugin {
fromAggressiveSplittingSet = new Set();
chunkSplitDataMap = new Map();
});
compilation.hooks.optimizeChunksAdvanced.tap(
"AggressiveSplittingPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "AggressiveSplittingPlugin",
stage: STAGE_ADVANCED
}),
chunks => {
const chunkGraph = compilation.chunkGraph;
// Precompute stuff

View File

@ -5,6 +5,8 @@
"use strict";
const { STAGE_BASIC } = require("../OptimizationStages");
class EnsureChunkConditionsPlugin {
apply(compiler) {
compiler.hooks.compilation.tap(
@ -58,8 +60,11 @@ class EnsureChunkConditionsPlugin {
}
if (changed) return true;
};
compilation.hooks.optimizeChunksBasic.tap(
"EnsureChunkConditionsPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "EnsureChunkConditionsPlugin",
stage: STAGE_BASIC
}),
handler
);
}

View File

@ -7,6 +7,7 @@
const validateOptions = require("schema-utils");
const schema = require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json");
const { STAGE_ADVANCED } = require("../OptimizationStages");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
@ -24,8 +25,11 @@ class LimitChunkCountPlugin {
apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap("LimitChunkCountPlugin", compilation => {
compilation.hooks.optimizeChunksAdvanced.tap(
"LimitChunkCountPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "LimitChunkCountPlugin",
stage: STAGE_ADVANCED
}),
chunks => {
const chunkGraph = compilation.chunkGraph;
const maxChunks = options.maxChunks;

View File

@ -5,6 +5,8 @@
"use strict";
const { STAGE_BASIC } = require("../OptimizationStages");
/** @typedef {import("../Compiler")} Compiler */
class MergeDuplicateChunksPlugin {
@ -16,8 +18,11 @@ class MergeDuplicateChunksPlugin {
compiler.hooks.compilation.tap(
"MergeDuplicateChunksPlugin",
compilation => {
compilation.hooks.optimizeChunksBasic.tap(
"MergeDuplicateChunksPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "MergeDuplicateChunksPlugin",
stage: STAGE_BASIC
}),
chunks => {
const chunkGraph = compilation.chunkGraph;

View File

@ -7,6 +7,7 @@
const validateOptions = require("schema-utils");
const schema = require("../../schemas/plugins/optimize/MinChunkSizePlugin.json");
const { STAGE_ADVANCED } = require("../OptimizationStages");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
@ -25,8 +26,11 @@ class MinChunkSizePlugin {
const options = this.options;
const minChunkSize = options.minChunkSize;
compiler.hooks.compilation.tap("MinChunkSizePlugin", compilation => {
compilation.hooks.optimizeChunksAdvanced.tap(
"MinChunkSizePlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "MinChunkSizePlugin",
stage: STAGE_ADVANCED
}),
chunks => {
const chunkGraph = compilation.chunkGraph;
const equalOptions = {

View File

@ -5,6 +5,7 @@
"use strict";
const { STAGE_DEFAULT } = require("../OptimizationStages");
const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
const ModuleHotAcceptDependency = require("../dependencies/ModuleHotAcceptDependency");
@ -97,7 +98,10 @@ class ModuleConcatenationPlugin {
};
compilation.hooks.optimizeChunkModules.tap(
"ModuleConcatenationPlugin",
/** @type {TODO} */ ({
name: "ModuleConcatenationPlugin",
stage: STAGE_DEFAULT
}),
(chunks, modules) => {
const chunkGraph = compilation.chunkGraph;
const relevantModules = [];

View File

@ -5,6 +5,8 @@
"use strict";
const { STAGE_BASIC, STAGE_ADVANCED } = require("../OptimizationStages");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
@ -33,12 +35,20 @@ class RemoveEmptyChunksPlugin {
}
}
};
compilation.hooks.optimizeChunksBasic.tap(
"RemoveEmptyChunksPlugin",
// TODO do it once
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "RemoveEmptyChunksPlugin",
stage: STAGE_BASIC
}),
handler
);
compilation.hooks.optimizeChunksAdvanced.tap(
"RemoveEmptyChunksPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "RemoveEmptyChunksPlugin",
stage: STAGE_ADVANCED
}),
handler
);
});

View File

@ -5,6 +5,7 @@
"use strict";
const { STAGE_BASIC } = require("../OptimizationStages");
const Queue = require("../util/Queue");
const { intersect } = require("../util/SetHelpers");
@ -100,8 +101,11 @@ class RemoveParentModulesPlugin {
}
}
};
compilation.hooks.optimizeChunksBasic.tap(
"RemoveParentModulesPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "RemoveParentModulesPlugin",
stage: STAGE_BASIC
}),
handler
);
});

View File

@ -5,7 +5,9 @@
"use strict";
module.exports = class RuntimeChunkPlugin {
const { STAGE_ADVANCED } = require("../OptimizationStages");
class RuntimeChunkPlugin {
constructor(options) {
this.options = Object.assign(
{
@ -17,27 +19,35 @@ module.exports = class RuntimeChunkPlugin {
apply(compiler) {
compiler.hooks.thisCompilation.tap("RuntimeChunkPlugin", compilation => {
compilation.hooks.optimizeChunksAdvanced.tap("RuntimeChunkPlugin", () => {
const chunkGraph = compilation.chunkGraph;
for (const entrypoint of compilation.entrypoints.values()) {
const chunk = entrypoint.getRuntimeChunk();
let name = this.options.name;
if (typeof name === "function") {
name = name(entrypoint);
}
if (
chunkGraph.getNumberOfChunkModules(chunk) > 0 ||
!chunk.preventIntegration ||
chunk.name !== name
) {
const newChunk = compilation.addChunk(name);
newChunk.preventIntegration = true;
entrypoint.unshiftChunk(newChunk);
newChunk.addGroup(entrypoint);
entrypoint.setRuntimeChunk(newChunk);
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "RuntimeChunkPlugin",
stage: STAGE_ADVANCED
}),
() => {
const chunkGraph = compilation.chunkGraph;
for (const entrypoint of compilation.entrypoints.values()) {
const chunk = entrypoint.getRuntimeChunk();
let name = this.options.name;
if (typeof name === "function") {
name = name(entrypoint);
}
if (
chunkGraph.getNumberOfChunkModules(chunk) > 0 ||
!chunk.preventIntegration ||
chunk.name !== name
) {
const newChunk = compilation.addChunk(name);
newChunk.preventIntegration = true;
entrypoint.unshiftChunk(newChunk);
newChunk.addGroup(entrypoint);
entrypoint.setRuntimeChunk(newChunk);
}
}
}
});
);
});
}
};
}
module.exports = RuntimeChunkPlugin;

View File

@ -6,6 +6,7 @@
"use strict";
const mm = require("micromatch");
const { STAGE_DEFAULT } = require("../OptimizationStages");
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
@ -56,7 +57,10 @@ class SideEffectsFlagPlugin {
compiler.hooks.compilation.tap("SideEffectsFlagPlugin", compilation => {
const moduleGraph = compilation.moduleGraph;
compilation.hooks.optimizeDependencies.tap(
"SideEffectsFlagPlugin",
/** @type {TODO} */ ({
name: "SideEffectsFlagPlugin",
stage: STAGE_DEFAULT
}),
modules => {
/** @type {Map<Module, Map<string, ExportInModule>>} */
const reexportMaps = new Map();

View File

@ -6,6 +6,7 @@
"use strict";
const crypto = require("crypto");
const { STAGE_ADVANCED } = require("../OptimizationStages");
const { isSubset } = require("../util/SetHelpers");
const SortableSet = require("../util/SortableSet");
const deterministicGrouping = require("../util/deterministicGrouping");
@ -335,8 +336,11 @@ module.exports = class SplitChunksPlugin {
compilation.hooks.unseal.tap("SplitChunksPlugin", () => {
alreadyOptimized = false;
});
compilation.hooks.optimizeChunksAdvanced.tap(
"SplitChunksPlugin",
compilation.hooks.optimizeChunks.tap(
/** @type {TODO} */ ({
name: "SplitChunksPlugin",
stage: STAGE_ADVANCED
}),
chunks => {
if (alreadyOptimized) return;
alreadyOptimized = true;

View File

@ -71,8 +71,8 @@ describe("StatsTestCases", () => {
c.hooks.compilation.tap("StatsTestCasesTest", compilation => {
[
"optimize",
"optimizeModulesBasic",
"optimizeChunksBasic",
"optimizeModules",
"optimizeChunks",
"afterOptimizeTree",
"afterOptimizeAssets",
"beforeHash"

View File

@ -156,8 +156,8 @@ const describeCases = config => {
this.hooks.compilation.tap("TestCasesTest", compilation => {
[
"optimize",
"optimizeModulesBasic",
"optimizeChunksBasic",
"optimizeModules",
"optimizeChunks",
"afterOptimizeTree",
"afterOptimizeAssets"
].forEach(hook => {