HashedModuleIdsPlugin.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { DEFAULTS } = require("../config/defaults");
  7. const {
  8. compareModulesByPreOrderIndexOrIdentifier
  9. } = require("../util/comparators");
  10. const createSchemaValidation = require("../util/create-schema-validation");
  11. const createHash = require("../util/createHash");
  12. const {
  13. getUsedModuleIdsAndModules,
  14. getFullModuleName
  15. } = require("./IdHelpers");
  16. /** @typedef {import("../../declarations/plugins/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
  17. /** @typedef {import("../Compiler")} Compiler */
  18. const validate = createSchemaValidation(
  19. require("../../schemas/plugins/HashedModuleIdsPlugin.check.js"),
  20. () => require("../../schemas/plugins/HashedModuleIdsPlugin.json"),
  21. {
  22. name: "Hashed Module Ids Plugin",
  23. baseDataPath: "options"
  24. }
  25. );
  26. const PLUGIN_NAME = "HashedModuleIdsPlugin";
  27. class HashedModuleIdsPlugin {
  28. /**
  29. * @param {HashedModuleIdsPluginOptions=} options options object
  30. */
  31. constructor(options = {}) {
  32. validate(options);
  33. /** @type {HashedModuleIdsPluginOptions} */
  34. this.options = {
  35. context: undefined,
  36. hashFunction: DEFAULTS.HASH_FUNCTION,
  37. hashDigest: "base64",
  38. hashDigestLength: 4,
  39. ...options
  40. };
  41. }
  42. /**
  43. * Apply the plugin
  44. * @param {Compiler} compiler the compiler instance
  45. * @returns {void}
  46. */
  47. apply(compiler) {
  48. const options = this.options;
  49. compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
  50. compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
  51. const chunkGraph = compilation.chunkGraph;
  52. const context = this.options.context
  53. ? this.options.context
  54. : compiler.context;
  55. const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
  56. const modulesInNaturalOrder = modules.sort(
  57. compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
  58. );
  59. for (const module of modulesInNaturalOrder) {
  60. const ident = getFullModuleName(module, context, compiler.root);
  61. const hash = createHash(
  62. /** @type {NonNullable<HashedModuleIdsPluginOptions["hashFunction"]>} */ (
  63. options.hashFunction
  64. )
  65. );
  66. hash.update(ident || "");
  67. const hashId = /** @type {string} */ (
  68. hash.digest(options.hashDigest)
  69. );
  70. let len = options.hashDigestLength;
  71. while (usedIds.has(hashId.slice(0, len)))
  72. /** @type {number} */ (len)++;
  73. const moduleId = hashId.slice(0, len);
  74. chunkGraph.setModuleId(module, moduleId);
  75. usedIds.add(moduleId);
  76. }
  77. });
  78. });
  79. }
  80. }
  81. module.exports = HashedModuleIdsPlugin;