LoaderOptionsPlugin.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
  7. const NormalModule = require("./NormalModule");
  8. const createSchemaValidation = require("./util/create-schema-validation");
  9. /** @typedef {import("../declarations/plugins/LoaderOptionsPlugin").LoaderOptionsPluginOptions} LoaderOptionsPluginOptions */
  10. /** @typedef {import("./Compiler")} Compiler */
  11. /** @typedef {import("./ModuleFilenameHelpers").Matcher} Matcher */
  12. /** @typedef {import("./ModuleFilenameHelpers").MatchObject} MatchObject */
  13. /**
  14. * @template T
  15. * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
  16. */
  17. const validate = createSchemaValidation(
  18. require("../schemas/plugins/LoaderOptionsPlugin.check"),
  19. () => require("../schemas/plugins/LoaderOptionsPlugin.json"),
  20. {
  21. name: "Loader Options Plugin",
  22. baseDataPath: "options"
  23. }
  24. );
  25. const PLUGIN_NAME = "LoaderOptionsPlugin";
  26. class LoaderOptionsPlugin {
  27. /**
  28. * @param {LoaderOptionsPluginOptions & MatchObject} options options object
  29. */
  30. constructor(options = {}) {
  31. validate(options);
  32. // If no options are set then generate empty options object
  33. if (typeof options !== "object") options = {};
  34. if (!options.test) {
  35. /** @type {Partial<RegExp>} */
  36. const defaultTrueMockRegExp = {
  37. test: () => true
  38. };
  39. /** @type {RegExp} */
  40. options.test =
  41. /** @type {RegExp} */
  42. (defaultTrueMockRegExp);
  43. }
  44. this.options = options;
  45. }
  46. /**
  47. * Apply the plugin
  48. * @param {Compiler} compiler the compiler instance
  49. * @returns {void}
  50. */
  51. apply(compiler) {
  52. const options = this.options;
  53. compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
  54. NormalModule.getCompilationHooks(compilation).loader.tap(
  55. PLUGIN_NAME,
  56. (context, module) => {
  57. const resource = module.resource;
  58. if (!resource) return;
  59. const i = resource.indexOf("?");
  60. if (
  61. ModuleFilenameHelpers.matchObject(
  62. options,
  63. i < 0 ? resource : resource.slice(0, i)
  64. )
  65. ) {
  66. for (const key of Object.keys(options)) {
  67. if (key === "include" || key === "exclude" || key === "test") {
  68. continue;
  69. }
  70. /** @type {LoaderContext<EXPECTED_ANY> & Record<string, EXPECTED_ANY>} */
  71. (context)[key] = options[key];
  72. }
  73. }
  74. }
  75. );
  76. });
  77. }
  78. }
  79. module.exports = LoaderOptionsPlugin;