ChunkModuleIdRangePlugin.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { find } = require("../util/SetHelpers");
  7. const {
  8. compareModulesByPostOrderIndexOrIdentifier,
  9. compareModulesByPreOrderIndexOrIdentifier
  10. } = require("../util/comparators");
  11. /** @typedef {import("../Compiler")} Compiler */
  12. /** @typedef {import("../Module")} Module */
  13. /** @typedef {import("../ChunkGraph").ModuleComparator} ModuleComparator */
  14. /**
  15. * Defines the chunk module id range plugin options type used by this module.
  16. * @typedef {object} ChunkModuleIdRangePluginOptions
  17. * @property {string} name the chunk name
  18. * @property {("index" | "index2" | "preOrderIndex" | "postOrderIndex")=} order order
  19. * @property {number=} start start id
  20. * @property {number=} end end id
  21. */
  22. const PLUGIN_NAME = "ChunkModuleIdRangePlugin";
  23. class ChunkModuleIdRangePlugin {
  24. /**
  25. * Creates an instance of ChunkModuleIdRangePlugin.
  26. * @param {ChunkModuleIdRangePluginOptions} options options object
  27. */
  28. constructor(options) {
  29. /** @type {ChunkModuleIdRangePluginOptions} */
  30. this.options = options;
  31. }
  32. /**
  33. * Applies the plugin by registering its hooks on the compiler.
  34. * @param {Compiler} compiler the compiler instance
  35. * @returns {void}
  36. */
  37. apply(compiler) {
  38. compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
  39. const moduleGraph = compilation.moduleGraph;
  40. compilation.hooks.moduleIds.tap(PLUGIN_NAME, (modules) => {
  41. const chunkGraph = compilation.chunkGraph;
  42. const chunk = find(
  43. compilation.chunks,
  44. (chunk) => chunk.name === this.options.name
  45. );
  46. if (!chunk) {
  47. throw new Error(
  48. `${PLUGIN_NAME}: Chunk with name '${this.options.name}"' was not found`
  49. );
  50. }
  51. /** @type {Module[]} */
  52. let chunkModules;
  53. if (this.options.order) {
  54. /** @type {ModuleComparator} */
  55. let cmpFn;
  56. switch (this.options.order) {
  57. case "index":
  58. case "preOrderIndex":
  59. cmpFn = compareModulesByPreOrderIndexOrIdentifier(moduleGraph);
  60. break;
  61. case "index2":
  62. case "postOrderIndex":
  63. cmpFn = compareModulesByPostOrderIndexOrIdentifier(moduleGraph);
  64. break;
  65. default:
  66. throw new Error(`${PLUGIN_NAME}: unexpected value of order`);
  67. }
  68. chunkModules = chunkGraph.getOrderedChunkModules(chunk, cmpFn);
  69. } else {
  70. chunkModules = [...modules]
  71. .filter((m) => chunkGraph.isModuleInChunk(m, chunk))
  72. .sort(compareModulesByPreOrderIndexOrIdentifier(moduleGraph));
  73. }
  74. let currentId = this.options.start || 0;
  75. for (let i = 0; i < chunkModules.length; i++) {
  76. const m = chunkModules[i];
  77. if (m.needId && chunkGraph.getModuleId(m) === null) {
  78. chunkGraph.setModuleId(m, currentId++);
  79. }
  80. if (this.options.end && currentId > this.options.end) break;
  81. }
  82. });
  83. });
  84. }
  85. }
  86. module.exports = ChunkModuleIdRangePlugin;