summaryrefslogtreecommitdiff
path: root/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
diff options
context:
space:
mode:
authorlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
committerlittleblack111 <littleblack11111@gmail.com>2023-10-31 15:37:35 +0800
commitd5f14083061f2ce6a42313188443a42e30796320 (patch)
treecc6a9889e08b29595a76a33b9e7b4ef84866468b /node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
parentb1a6ea021f29f182b62f9f81024a3d8ac8621b7f (diff)
added make browserlist(autoprefixer) work fixed
Diffstat (limited to 'node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js')
-rw-r--r--node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js281
1 files changed, 281 insertions, 0 deletions
diff --git a/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
new file mode 100644
index 00000000..445719b6
--- /dev/null
+++ b/node_modules/webpack/lib/optimize/LimitChunkCountPlugin.js
@@ -0,0 +1,281 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Tobias Koppers @sokra
+*/
+
+"use strict";
+
+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.js"),
+ () => require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json"),
+ {
+ name: "Limit Chunk Count Plugin",
+ baseDataPath: "options"
+ }
+);
+
+/**
+ * @typedef {Object} ChunkCombination
+ * @property {boolean} deleted this is set to true when combination was removed
+ * @property {number} sizeDiff
+ * @property {number} integratedSize
+ * @property {Chunk} a
+ * @property {Chunk} b
+ * @property {number} aIdx
+ * @property {number} bIdx
+ * @property {number} aSize
+ * @property {number} bSize
+ */
+
+/**
+ * @template K, V
+ * @param {Map<K, Set<V>>} map map
+ * @param {K} key key
+ * @param {V} value value
+ */
+const addToSetMap = (map, key, value) => {
+ const set = map.get(key);
+ if (set === undefined) {
+ map.set(key, new Set([value]));
+ } else {
+ set.add(value);
+ }
+};
+
+class LimitChunkCountPlugin {
+ /**
+ * @param {LimitChunkCountPluginOptions=} options options object
+ */
+ constructor(options) {
+ validate(options);
+ this.options = options;
+ }
+
+ /**
+ * @param {Compiler} compiler the webpack compiler
+ * @returns {void}
+ */
+ apply(compiler) {
+ const options = this.options;
+ compiler.hooks.compilation.tap("LimitChunkCountPlugin", compilation => {
+ compilation.hooks.optimizeChunks.tap(
+ {
+ name: "LimitChunkCountPlugin",
+ stage: STAGE_ADVANCED
+ },
+ chunks => {
+ const chunkGraph = compilation.chunkGraph;
+ const maxChunks =
+ /** @type {LimitChunkCountPluginOptions} */
+ (options).maxChunks;
+ if (!maxChunks) return;
+ if (maxChunks < 1) return;
+ if (compilation.chunks.size <= maxChunks) return;
+
+ let remainingChunksToMerge = compilation.chunks.size - maxChunks;
+
+ // order chunks in a deterministic way
+ const compareChunksWithGraph = compareChunks(chunkGraph);
+ const orderedChunks = Array.from(chunks).sort(compareChunksWithGraph);
+
+ // create a lazy sorted data structure to keep all combinations
+ // this is large. Size = chunks * (chunks - 1) / 2
+ // It uses a multi layer bucket sort plus normal sort in the last layer
+ // It's also lazy so only accessed buckets are sorted
+ const combinations = new LazyBucketSortedSet(
+ // Layer 1: ordered by largest size benefit
+ c => c.sizeDiff,
+ (a, b) => b - a,
+ // Layer 2: ordered by smallest combined size
+ /**
+ * @param {ChunkCombination} c combination
+ * @returns {number} integrated size
+ */
+ c => c.integratedSize,
+ (a, b) => a - b,
+ // Layer 3: ordered by position difference in orderedChunk (-> to be deterministic)
+ /**
+ * @param {ChunkCombination} c combination
+ * @returns {number} position difference
+ */
+ c => c.bIdx - c.aIdx,
+ (a, b) => a - b,
+ // Layer 4: ordered by position in orderedChunk (-> to be deterministic)
+ (a, b) => a.bIdx - b.bIdx
+ );
+
+ // we keep a mapping from chunk to all combinations
+ // but this mapping is not kept up-to-date with deletions
+ // so `deleted` flag need to be considered when iterating this
+ /** @type {Map<Chunk, Set<ChunkCombination>>} */
+ const combinationsByChunk = new Map();
+
+ orderedChunks.forEach((b, bIdx) => {
+ // create combination pairs with size and integrated size
+ for (let aIdx = 0; aIdx < bIdx; aIdx++) {
+ const a = orderedChunks[aIdx];
+ // filter pairs that can not be integrated!
+ if (!chunkGraph.canChunksBeIntegrated(a, b)) continue;
+
+ const integratedSize = chunkGraph.getIntegratedChunksSize(
+ a,
+ b,
+ options
+ );
+
+ const aSize = chunkGraph.getChunkSize(a, options);
+ const bSize = chunkGraph.getChunkSize(b, options);
+ const c = {
+ deleted: false,
+ sizeDiff: aSize + bSize - integratedSize,
+ integratedSize,
+ a,
+ b,
+ aIdx,
+ bIdx,
+ aSize,
+ bSize
+ };
+ combinations.add(c);
+ addToSetMap(combinationsByChunk, a, c);
+ addToSetMap(combinationsByChunk, b, c);
+ }
+ return combinations;
+ });
+
+ // list of modified chunks during this run
+ // combinations affected by this change are skipped to allow
+ // further optimizations
+ /** @type {Set<Chunk>} */
+ const modifiedChunks = new Set();
+
+ let changed = false;
+ // eslint-disable-next-line no-constant-condition
+ loop: while (true) {
+ const combination = combinations.popFirst();
+ if (combination === undefined) break;
+
+ combination.deleted = true;
+ const { a, b, integratedSize } = combination;
+
+ // skip over pair when
+ // one of the already merged chunks is a parent of one of the chunks
+ if (modifiedChunks.size > 0) {
+ const queue = new Set(a.groupsIterable);
+ for (const group of b.groupsIterable) {
+ queue.add(group);
+ }
+ for (const group of queue) {
+ for (const mChunk of modifiedChunks) {
+ if (mChunk !== a && mChunk !== b && mChunk.isInGroup(group)) {
+ // This is a potential pair which needs recalculation
+ // We can't do that now, but it merge before following pairs
+ // so we leave space for it, and consider chunks as modified
+ // just for the worse case
+ remainingChunksToMerge--;
+ if (remainingChunksToMerge <= 0) break loop;
+ modifiedChunks.add(a);
+ modifiedChunks.add(b);
+ continue loop;
+ }
+ }
+ for (const parent of group.parentsIterable) {
+ queue.add(parent);
+ }
+ }
+ }
+
+ // merge the chunks
+ if (chunkGraph.canChunksBeIntegrated(a, b)) {
+ chunkGraph.integrateChunks(a, b);
+ compilation.chunks.delete(b);
+
+ // flag chunk a as modified as further optimization are possible for all children here
+ modifiedChunks.add(a);
+
+ changed = true;
+ remainingChunksToMerge--;
+ if (remainingChunksToMerge <= 0) break;
+
+ // Update all affected combinations
+ // delete all combination with the removed chunk
+ // we will use combinations with the kept chunk instead
+ for (const combination of /** @type {Set<ChunkCombination>} */ (
+ combinationsByChunk.get(a)
+ )) {
+ if (combination.deleted) continue;
+ combination.deleted = true;
+ combinations.delete(combination);
+ }
+
+ // Update combinations with the kept chunk with new sizes
+ for (const combination of /** @type {Set<ChunkCombination>} */ (
+ combinationsByChunk.get(b)
+ )) {
+ if (combination.deleted) continue;
+ if (combination.a === b) {
+ if (!chunkGraph.canChunksBeIntegrated(a, combination.b)) {
+ combination.deleted = true;
+ combinations.delete(combination);
+ continue;
+ }
+ // Update size
+ const newIntegratedSize = chunkGraph.getIntegratedChunksSize(
+ a,
+ combination.b,
+ options
+ );
+ const finishUpdate = combinations.startUpdate(combination);
+ combination.a = a;
+ combination.integratedSize = newIntegratedSize;
+ combination.aSize = integratedSize;
+ combination.sizeDiff =
+ combination.bSize + integratedSize - newIntegratedSize;
+ finishUpdate();
+ } else if (combination.b === b) {
+ if (!chunkGraph.canChunksBeIntegrated(combination.a, a)) {
+ combination.deleted = true;
+ combinations.delete(combination);
+ continue;
+ }
+ // Update size
+ const newIntegratedSize = chunkGraph.getIntegratedChunksSize(
+ combination.a,
+ a,
+ options
+ );
+
+ const finishUpdate = combinations.startUpdate(combination);
+ combination.b = a;
+ combination.integratedSize = newIntegratedSize;
+ combination.bSize = integratedSize;
+ combination.sizeDiff =
+ integratedSize + combination.aSize - newIntegratedSize;
+ finishUpdate();
+ }
+ }
+ combinationsByChunk.set(
+ a,
+ /** @type {Set<ChunkCombination>} */ (
+ combinationsByChunk.get(b)
+ )
+ );
+ combinationsByChunk.delete(b);
+ }
+ }
+ if (changed) return true;
+ }
+ );
+ });
+ }
+}
+module.exports = LimitChunkCountPlugin;