AggressiveMergingPlugin.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. /** @typedef {import("../Chunk")} Chunk */
  8. /** @typedef {import("../Compiler")} Compiler */
  9. class AggressiveMergingPlugin {
  10. constructor(options) {
  11. if (
  12. (options !== undefined && typeof options !== "object") ||
  13. Array.isArray(options)
  14. ) {
  15. throw new Error(
  16. "Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/"
  17. );
  18. }
  19. this.options = options || {};
  20. }
  21. /**
  22. * Apply the plugin
  23. * @param {Compiler} compiler the compiler instance
  24. * @returns {void}
  25. */
  26. apply(compiler) {
  27. const options = this.options;
  28. const minSizeReduce = options.minSizeReduce || 1.5;
  29. compiler.hooks.thisCompilation.tap(
  30. "AggressiveMergingPlugin",
  31. compilation => {
  32. compilation.hooks.optimizeChunks.tap(
  33. {
  34. name: "AggressiveMergingPlugin",
  35. stage: STAGE_ADVANCED
  36. },
  37. chunks => {
  38. const chunkGraph = compilation.chunkGraph;
  39. /** @type {{a: Chunk, b: Chunk, improvement: number}[]} */
  40. let combinations = [];
  41. for (const a of chunks) {
  42. if (a.canBeInitial()) continue;
  43. for (const b of chunks) {
  44. if (b.canBeInitial()) continue;
  45. if (b === a) break;
  46. if (!chunkGraph.canChunksBeIntegrated(a, b)) {
  47. continue;
  48. }
  49. const aSize = chunkGraph.getChunkSize(b, {
  50. chunkOverhead: 0
  51. });
  52. const bSize = chunkGraph.getChunkSize(a, {
  53. chunkOverhead: 0
  54. });
  55. const abSize = chunkGraph.getIntegratedChunksSize(b, a, {
  56. chunkOverhead: 0
  57. });
  58. const improvement = (aSize + bSize) / abSize;
  59. combinations.push({
  60. a,
  61. b,
  62. improvement
  63. });
  64. }
  65. }
  66. combinations.sort((a, b) => {
  67. return b.improvement - a.improvement;
  68. });
  69. const pair = combinations[0];
  70. if (!pair) return;
  71. if (pair.improvement < minSizeReduce) return;
  72. chunkGraph.integrateChunks(pair.b, pair.a);
  73. compilation.chunks.delete(pair.a);
  74. return true;
  75. }
  76. );
  77. }
  78. );
  79. }
  80. }
  81. module.exports = AggressiveMergingPlugin;