MinChunkSizePlugin.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { STAGE_ADVANCED } = require("../OptimizationStages");
  7. /**
  8. * @import {
  9. * MinChunkSizePluginOptions
  10. * } from "../../declarations/plugins/optimize/MinChunkSizePlugin"
  11. */
  12. /** @import Chunk from "../Chunk" */
  13. /** @import Compiler from "../Compiler" */
  14. const PLUGIN_NAME = "MinChunkSizePlugin";
  15. class MinChunkSizePlugin {
  16. /**
  17. * Creates an instance of MinChunkSizePlugin.
  18. * @param {MinChunkSizePluginOptions} options options object
  19. */
  20. constructor(options) {
  21. /** @type {MinChunkSizePluginOptions} */
  22. this.options = options;
  23. }
  24. /**
  25. * Applies the plugin by registering its hooks on the compiler.
  26. * @param {Compiler} compiler the compiler instance
  27. * @returns {void}
  28. */
  29. apply(compiler) {
  30. compiler.hooks.validate.tap(PLUGIN_NAME, () => {
  31. compiler.validate(
  32. () => require("../../schemas/plugins/optimize/MinChunkSizePlugin.json"),
  33. this.options,
  34. {
  35. name: "Min Chunk Size Plugin",
  36. baseDataPath: "options"
  37. },
  38. (options) =>
  39. require("../../schemas/plugins/optimize/MinChunkSizePlugin.check")(
  40. options
  41. )
  42. );
  43. });
  44. compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
  45. compilation.hooks.optimizeChunks.tap(
  46. {
  47. name: PLUGIN_NAME,
  48. stage: STAGE_ADVANCED
  49. },
  50. (chunks) => {
  51. const chunkGraph = compilation.chunkGraph;
  52. const equalOptions = {
  53. chunkOverhead: 1,
  54. entryChunkMultiplicator: 1
  55. };
  56. /** @type {Map<Chunk, number>} */
  57. const chunkSizesMap = new Map();
  58. /** @type {[Chunk, Chunk][]} */
  59. const combinations = [];
  60. /** @type {Chunk[]} */
  61. const smallChunks = [];
  62. /** @type {Chunk[]} */
  63. const visitedChunks = [];
  64. for (const a of chunks) {
  65. // check if one of the chunks sizes is smaller than the minChunkSize
  66. // and filter pairs that can NOT be integrated!
  67. if (
  68. chunkGraph.getChunkSize(a, equalOptions) <
  69. this.options.minChunkSize
  70. ) {
  71. smallChunks.push(a);
  72. for (const b of visitedChunks) {
  73. if (chunkGraph.canChunksBeIntegrated(b, a)) {
  74. combinations.push([b, a]);
  75. }
  76. }
  77. } else {
  78. for (const b of smallChunks) {
  79. if (chunkGraph.canChunksBeIntegrated(b, a)) {
  80. combinations.push([b, a]);
  81. }
  82. }
  83. }
  84. chunkSizesMap.set(a, chunkGraph.getChunkSize(a, this.options));
  85. visitedChunks.push(a);
  86. }
  87. const sortedSizeFilteredExtendedPairCombinations = combinations
  88. .map((pair) => {
  89. // extend combination pairs with size and integrated size
  90. const a = /** @type {number} */ (chunkSizesMap.get(pair[0]));
  91. const b = /** @type {number} */ (chunkSizesMap.get(pair[1]));
  92. const ab = chunkGraph.getIntegratedChunksSize(
  93. pair[0],
  94. pair[1],
  95. this.options
  96. );
  97. /** @type {[number, number, Chunk, Chunk]} */
  98. const extendedPair = [a + b - ab, ab, pair[0], pair[1]];
  99. return extendedPair;
  100. })
  101. .sort((a, b) => {
  102. // sadly javascript does an in place sort here
  103. // sort by size
  104. const diff = b[0] - a[0];
  105. if (diff !== 0) return diff;
  106. return a[1] - b[1];
  107. });
  108. if (sortedSizeFilteredExtendedPairCombinations.length === 0) return;
  109. const pair = sortedSizeFilteredExtendedPairCombinations[0];
  110. chunkGraph.integrateChunks(pair[2], pair[3]);
  111. compilation.chunks.delete(pair[3]);
  112. return true;
  113. }
  114. );
  115. });
  116. }
  117. }
  118. module.exports = MinChunkSizePlugin;