MergeDuplicateChunksPlugin.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. class MergeDuplicateChunksPlugin {
  7. apply(compiler) {
  8. compiler.hooks.compilation.tap(
  9. "MergeDuplicateChunksPlugin",
  10. compilation => {
  11. compilation.hooks.optimizeChunksBasic.tap(
  12. "MergeDuplicateChunksPlugin",
  13. chunks => {
  14. // remember already tested chunks for performance
  15. const notDuplicates = new Set();
  16. // for each chunk
  17. for (const chunk of chunks) {
  18. // track a Set of all chunk that could be duplicates
  19. let possibleDuplicates;
  20. for (const module of chunk.modulesIterable) {
  21. if (possibleDuplicates === undefined) {
  22. // when possibleDuplicates is not yet set,
  23. // create a new Set from chunks of the current module
  24. // including only chunks with the same number of modules
  25. for (const dup of module.chunksIterable) {
  26. if (
  27. dup !== chunk &&
  28. chunk.getNumberOfModules() === dup.getNumberOfModules() &&
  29. !notDuplicates.has(dup)
  30. ) {
  31. // delay allocating the new Set until here, reduce memory pressure
  32. if (possibleDuplicates === undefined) {
  33. possibleDuplicates = new Set();
  34. }
  35. possibleDuplicates.add(dup);
  36. }
  37. }
  38. // when no chunk is possible we can break here
  39. if (possibleDuplicates === undefined) break;
  40. } else {
  41. // validate existing possible duplicates
  42. for (const dup of possibleDuplicates) {
  43. // remove possible duplicate when module is not contained
  44. if (!dup.containsModule(module)) {
  45. possibleDuplicates.delete(dup);
  46. }
  47. }
  48. // when all chunks has been removed we can break here
  49. if (possibleDuplicates.size === 0) break;
  50. }
  51. }
  52. // when we found duplicates
  53. if (
  54. possibleDuplicates !== undefined &&
  55. possibleDuplicates.size > 0
  56. ) {
  57. for (const otherChunk of possibleDuplicates) {
  58. if (otherChunk.hasRuntime() !== chunk.hasRuntime()) continue;
  59. // merge them
  60. if (chunk.integrate(otherChunk, "duplicate")) {
  61. chunks.splice(chunks.indexOf(otherChunk), 1);
  62. }
  63. }
  64. }
  65. // don't check already processed chunks twice
  66. notDuplicates.add(chunk);
  67. }
  68. }
  69. );
  70. }
  71. );
  72. }
  73. }
  74. module.exports = MergeDuplicateChunksPlugin;