LimitChunkCountPlugin.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const validateOptions = require("schema-utils");
  7. const schema = require("../../schemas/plugins/optimize/LimitChunkCountPlugin.json");
  8. /** @typedef {import("../../declarations/plugins/optimize/LimitChunkCountPlugin").LimitChunkCountPluginOptions} LimitChunkCountPluginOptions */
  9. class LimitChunkCountPlugin {
  10. /**
  11. * @param {LimitChunkCountPluginOptions=} options options object
  12. */
  13. constructor(options) {
  14. if (!options) options = {};
  15. validateOptions(schema, options, "Limit Chunk Count Plugin");
  16. this.options = options;
  17. }
  18. apply(compiler) {
  19. const options = this.options;
  20. compiler.hooks.compilation.tap("LimitChunkCountPlugin", compilation => {
  21. compilation.hooks.optimizeChunksAdvanced.tap(
  22. "LimitChunkCountPlugin",
  23. chunks => {
  24. const maxChunks = options.maxChunks;
  25. if (!maxChunks) return;
  26. if (maxChunks < 1) return;
  27. if (chunks.length <= maxChunks) return;
  28. const orderedChunks = chunks.slice().sort((a, b) => a.compareTo(b));
  29. const sortedExtendedPairCombinations = orderedChunks
  30. .reduce((combinations, a, idx) => {
  31. // create combination pairs
  32. for (let i = 0; i < idx; i++) {
  33. const b = orderedChunks[i];
  34. combinations.push([b, a]);
  35. }
  36. return combinations;
  37. }, [])
  38. .map(pair => {
  39. // extend combination pairs with size and integrated size
  40. const a = pair[0].size(options);
  41. const b = pair[1].size(options);
  42. const ab = pair[0].integratedSize(pair[1], options);
  43. return [a + b - ab, ab, pair[0], pair[1], a, b];
  44. })
  45. .filter(extendedPair => {
  46. // filter pairs that do not have an integratedSize
  47. // meaning they can NOT be integrated!
  48. return extendedPair[1] !== false;
  49. })
  50. .sort((a, b) => {
  51. // sadly javascript does an inplace sort here
  52. // sort them by size
  53. const diff1 = b[0] - a[0];
  54. if (diff1 !== 0) return diff1;
  55. const diff2 = a[1] - b[1];
  56. if (diff2 !== 0) return diff2;
  57. const diff3 = a[2].compareTo(b[2]);
  58. if (diff3 !== 0) return diff3;
  59. return a[3].compareTo(b[3]);
  60. });
  61. const pair = sortedExtendedPairCombinations[0];
  62. if (pair && pair[2].integrate(pair[3], "limit")) {
  63. chunks.splice(chunks.indexOf(pair[3]), 1);
  64. return true;
  65. }
  66. }
  67. );
  68. });
  69. }
  70. }
  71. module.exports = LimitChunkCountPlugin;