| | |
| | | const { STAGE_ADVANCED } = require("../OptimizationStages"); |
| | | const LazyBucketSortedSet = require("../util/LazyBucketSortedSet"); |
| | | const { compareChunks } = require("../util/comparators"); |
| | | const createSchemaValidation = require("../util/create-schema-validation"); |
| | | |
| | | /** @typedef {import("../../declarations/plugins/optimize/LimitChunkCountPlugin").LimitChunkCountPluginOptions} LimitChunkCountPluginOptions */ |
| | | /** @typedef {import("../Chunk")} Chunk */ |
| | | /** @typedef {import("../Compiler")} Compiler */ |
| | | |
| | | const validate = createSchemaValidation( |
| | | require("../../schemas/plugins/optimize/LimitChunkCountPlugin.check"), |
| | | () => require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json"), |
| | | { |
| | | name: "Limit Chunk Count Plugin", |
| | | baseDataPath: "options" |
| | | } |
| | | ); |
| | | |
| | | /** |
| | | * Defines the chunk combination type used by this module. |
| | | * @typedef {object} ChunkCombination |
| | | * @property {boolean} deleted this is set to true when combination was removed |
| | | * @property {number} sizeDiff |
| | |
| | | */ |
| | | |
| | | /** |
| | | * Adds the provided map to this object. |
| | | * @template K, V |
| | | * @param {Map<K, Set<V>>} map map |
| | | * @param {K} key key |
| | |
| | | |
| | | class LimitChunkCountPlugin { |
| | | /** |
| | | * Creates an instance of LimitChunkCountPlugin. |
| | | * @param {LimitChunkCountPluginOptions=} options options object |
| | | */ |
| | | constructor(options) { |
| | | validate(options); |
| | | this.options = /** @type {LimitChunkCountPluginOptions} */ (options); |
| | | constructor(options = { maxChunks: 1 }) { |
| | | /** @type {LimitChunkCountPluginOptions} */ |
| | | this.options = options; |
| | | } |
| | | |
| | | /** |
| | | * Applies the plugin by registering its hooks on the compiler. |
| | | * @param {Compiler} compiler the webpack compiler |
| | | * @returns {void} |
| | | */ |
| | | apply(compiler) { |
| | | const options = this.options; |
| | | compiler.hooks.validate.tap(PLUGIN_NAME, () => { |
| | | compiler.validate( |
| | | () => |
| | | require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json"), |
| | | this.options, |
| | | { |
| | | name: "Limit Chunk Count Plugin", |
| | | baseDataPath: "options" |
| | | }, |
| | | (options) => |
| | | require("../../schemas/plugins/optimize/LimitChunkCountPlugin.check")( |
| | | options |
| | | ) |
| | | ); |
| | | }); |
| | | |
| | | compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { |
| | | compilation.hooks.optimizeChunks.tap( |
| | | { |
| | |
| | | }, |
| | | (chunks) => { |
| | | const chunkGraph = compilation.chunkGraph; |
| | | const maxChunks = options.maxChunks; |
| | | const maxChunks = this.options.maxChunks; |
| | | if (!maxChunks) return; |
| | | if (maxChunks < 1) return; |
| | | if (compilation.chunks.size <= maxChunks) return; |
| | |
| | | |
| | | // Layer 2: ordered by smallest combined size |
| | | /** |
| | | * Handles the stage callback for this hook. |
| | | * @param {ChunkCombination} c combination |
| | | * @returns {number} integrated size |
| | | */ |
| | | (c) => c.integratedSize, |
| | | /** |
| | | * Handles the callback logic for this hook. |
| | | * @param {number} a a |
| | | * @param {number} b b |
| | | * @returns {number} result |
| | |
| | | |
| | | // Layer 3: ordered by position difference in orderedChunk (-> to be deterministic) |
| | | /** |
| | | * Handles the callback logic for this hook. |
| | | * @param {ChunkCombination} c combination |
| | | * @returns {number} position difference |
| | | */ |
| | | (c) => c.bIdx - c.aIdx, |
| | | /** |
| | | * Handles the callback logic for this hook. |
| | | * @param {number} a a |
| | | * @param {number} b b |
| | | * @returns {number} result |
| | |
| | | |
| | | // Layer 4: ordered by position in orderedChunk (-> to be deterministic) |
| | | /** |
| | | * Handles the callback logic for this hook. |
| | | * @param {ChunkCombination} a a |
| | | * @param {ChunkCombination} b b |
| | | * @returns {number} result |
| | |
| | | const integratedSize = chunkGraph.getIntegratedChunksSize( |
| | | a, |
| | | b, |
| | | options |
| | | this.options |
| | | ); |
| | | |
| | | const aSize = chunkGraph.getChunkSize(a, options); |
| | | const bSize = chunkGraph.getChunkSize(b, options); |
| | | const aSize = chunkGraph.getChunkSize(a, this.options); |
| | | const bSize = chunkGraph.getChunkSize(b, this.options); |
| | | /** @type {ChunkCombination} */ |
| | | const c = { |
| | | deleted: false, |
| | |
| | | const newIntegratedSize = chunkGraph.getIntegratedChunksSize( |
| | | a, |
| | | combination.b, |
| | | options |
| | | this.options |
| | | ); |
| | | const finishUpdate = combinations.startUpdate(combination); |
| | | combination.a = a; |
| | |
| | | const newIntegratedSize = chunkGraph.getIntegratedChunksSize( |
| | | combination.a, |
| | | a, |
| | | options |
| | | this.options |
| | | ); |
| | | |
| | | const finishUpdate = combinations.startUpdate(combination); |