ChunkModuleIdRangePlugin.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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. * @typedef {object} ChunkModuleIdRangePluginOptions
  16. * @property {string} name the chunk name
  17. * @property {("index" | "index2" | "preOrderIndex" | "postOrderIndex")=} order order
  18. * @property {number=} start start id
  19. * @property {number=} end end id
  20. */
  21. const PLUGIN_NAME = "ChunkModuleIdRangePlugin";
  22. class ChunkModuleIdRangePlugin {
  23. /**
  24. * @param {ChunkModuleIdRangePluginOptions} options options object
  25. */
  26. constructor(options) {
  27. /** @type {ChunkModuleIdRangePluginOptions} */
  28. this.options = options;
  29. }
  30. /**
  31. * Apply the plugin
  32. * @param {Compiler} compiler the compiler instance
  33. * @returns {void}
  34. */
  35. apply(compiler) {
  36. compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
  37. const moduleGraph = compilation.moduleGraph;
  38. compilation.hooks.moduleIds.tap(PLUGIN_NAME, (modules) => {
  39. const chunkGraph = compilation.chunkGraph;
  40. const chunk = find(
  41. compilation.chunks,
  42. (chunk) => chunk.name === this.options.name
  43. );
  44. if (!chunk) {
  45. throw new Error(
  46. `${PLUGIN_NAME}: Chunk with name '${this.options.name}"' was not found`
  47. );
  48. }
  49. /** @type {Module[]} */
  50. let chunkModules;
  51. if (this.options.order) {
  52. /** @type {ModuleComparator} */
  53. let cmpFn;
  54. switch (this.options.order) {
  55. case "index":
  56. case "preOrderIndex":
  57. cmpFn = compareModulesByPreOrderIndexOrIdentifier(moduleGraph);
  58. break;
  59. case "index2":
  60. case "postOrderIndex":
  61. cmpFn = compareModulesByPostOrderIndexOrIdentifier(moduleGraph);
  62. break;
  63. default:
  64. throw new Error(`${PLUGIN_NAME}: unexpected value of order`);
  65. }
  66. chunkModules = chunkGraph.getOrderedChunkModules(chunk, cmpFn);
  67. } else {
  68. chunkModules = [...modules]
  69. .filter((m) => chunkGraph.isModuleInChunk(m, chunk))
  70. .sort(compareModulesByPreOrderIndexOrIdentifier(moduleGraph));
  71. }
  72. let currentId = this.options.start || 0;
  73. for (let i = 0; i < chunkModules.length; i++) {
  74. const m = chunkModules[i];
  75. if (m.needId && chunkGraph.getModuleId(m) === null) {
  76. chunkGraph.setModuleId(m, currentId++);
  77. }
  78. if (this.options.end && currentId > this.options.end) break;
  79. }
  80. });
  81. });
  82. }
  83. }
  84. module.exports = ChunkModuleIdRangePlugin;