AggressiveMergingPlugin.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. class AggressiveMergingPlugin {
  7. constructor(options) {
  8. if(options !== undefined && typeof options !== "object" || Array.isArray(options)) {
  9. throw new Error("Argument should be an options object. To use defaults, pass in nothing.\nFor more info on options, see https://webpack.js.org/plugins/");
  10. }
  11. this.options = options || {};
  12. }
  13. apply(compiler) {
  14. const options = this.options;
  15. const minSizeReduce = options.minSizeReduce || 1.5;
  16. function getParentsWeight(chunk) {
  17. return chunk.parents.map((p) => {
  18. return p.isInitial() ? options.entryChunkMultiplicator || 10 : 1;
  19. }).reduce((a, b) => {
  20. return a + b;
  21. }, 0);
  22. }
  23. compiler.plugin("compilation", (compilation) => {
  24. compilation.plugin("optimize-chunks-advanced", (chunks) => {
  25. let combinations = [];
  26. chunks.forEach((a, idx) => {
  27. if(a.isInitial()) return;
  28. for(let i = 0; i < idx; i++) {
  29. const b = chunks[i];
  30. if(b.isInitial()) continue;
  31. combinations.push([b, a]);
  32. }
  33. });
  34. combinations.forEach((pair) => {
  35. const a = pair[0].size({
  36. chunkOverhead: 0
  37. });
  38. const b = pair[1].size({
  39. chunkOverhead: 0
  40. });
  41. const ab = pair[0].integratedSize(pair[1], {
  42. chunkOverhead: 0
  43. });
  44. pair.push({
  45. a: a,
  46. b: b,
  47. ab: ab
  48. });
  49. let newSize;
  50. if(ab === false) {
  51. pair.unshift(false);
  52. } else if(options.moveToParents) {
  53. const aOnly = ab - b;
  54. const bOnly = ab - a;
  55. const common = a + b - ab;
  56. newSize = common + getParentsWeight(pair[0]) * aOnly + getParentsWeight(pair[1]) * bOnly;
  57. pair.push({
  58. aOnly: aOnly,
  59. bOnly: bOnly,
  60. common: common,
  61. newSize: newSize
  62. });
  63. } else {
  64. newSize = ab;
  65. }
  66. pair.unshift((a + b) / newSize);
  67. });
  68. combinations = combinations.filter((pair) => {
  69. return pair[0] !== false;
  70. });
  71. combinations.sort((a, b) => {
  72. return b[0] - a[0];
  73. });
  74. const pair = combinations[0];
  75. if(!pair) return;
  76. if(pair[0] < minSizeReduce) return;
  77. if(options.moveToParents) {
  78. const commonModules = pair[1].modules.filter((m) => {
  79. return pair[2].modules.indexOf(m) >= 0;
  80. });
  81. const aOnlyModules = pair[1].modules.filter((m) => {
  82. return commonModules.indexOf(m) < 0;
  83. });
  84. const bOnlyModules = pair[2].modules.filter((m) => {
  85. return commonModules.indexOf(m) < 0;
  86. });
  87. aOnlyModules.forEach((m) => {
  88. pair[1].removeModule(m);
  89. m.removeChunk(pair[1]);
  90. pair[1].parents.forEach((c) => {
  91. c.addModule(m);
  92. m.addChunk(c);
  93. });
  94. });
  95. bOnlyModules.forEach((m) => {
  96. pair[2].removeModule(m);
  97. m.removeChunk(pair[2]);
  98. pair[2].parents.forEach((c) => {
  99. c.addModule(m);
  100. m.addChunk(c);
  101. });
  102. });
  103. }
  104. if(pair[1].integrate(pair[2], "aggressive-merge")) {
  105. chunks.splice(chunks.indexOf(pair[2]), 1);
  106. return true;
  107. }
  108. });
  109. });
  110. }
  111. }
  112. module.exports = AggressiveMergingPlugin;