LoaderOptionsPlugin.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. /** @typedef {import("../declarations/plugins/LoaderOptionsPlugin").LoaderOptionsPluginOptions} LoaderOptionsPluginOptions */
  9. /** @typedef {import("./Compiler")} Compiler */
  10. /** @typedef {import("./ModuleFilenameHelpers").MatchObject} MatchObject */
  11. /**
  12. * Defines the loader context type used by this module.
  13. * @template T
  14. * @typedef {import("../declarations/LoaderContext").LoaderContext<T>} LoaderContext
  15. */
  16. const PLUGIN_NAME = "LoaderOptionsPlugin";
  17. class LoaderOptionsPlugin {
  18. /**
  19. * Creates an instance of LoaderOptionsPlugin.
  20. * @param {LoaderOptionsPluginOptions & MatchObject} options options object
  21. */
  22. constructor(options = {}) {
  23. // If no options are set then generate empty options object
  24. if (typeof options !== "object") options = {};
  25. if (!options.test) {
  26. options.test = () => true;
  27. }
  28. /** @type {LoaderOptionsPluginOptions & MatchObject} */
  29. this.options = options;
  30. }
  31. /**
  32. * Applies the plugin by registering its hooks on the compiler.
  33. * @param {Compiler} compiler the compiler instance
  34. * @returns {void}
  35. */
  36. apply(compiler) {
  37. compiler.hooks.validate.tap(PLUGIN_NAME, () => {
  38. compiler.validate(
  39. () => require("../schemas/plugins/LoaderOptionsPlugin.json"),
  40. this.options,
  41. {
  42. name: "Loader Options Plugin",
  43. baseDataPath: "options"
  44. },
  45. (options) =>
  46. require("../schemas/plugins/LoaderOptionsPlugin.check")(options)
  47. );
  48. });
  49. compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
  50. NormalModule.getCompilationHooks(compilation).loader.tap(
  51. PLUGIN_NAME,
  52. (context, module) => {
  53. const resource = module.resource;
  54. if (!resource) return;
  55. const i = resource.indexOf("?");
  56. if (
  57. ModuleFilenameHelpers.matchObject(
  58. this.options,
  59. i < 0 ? resource : resource.slice(0, i)
  60. )
  61. ) {
  62. for (const key of Object.keys(this.options)) {
  63. if (key === "include" || key === "exclude" || key === "test") {
  64. continue;
  65. }
  66. /** @type {LoaderContext<EXPECTED_ANY> & Record<string, EXPECTED_ANY>} */
  67. (context)[key] = this.options[key];
  68. }
  69. }
  70. }
  71. );
  72. });
  73. }
  74. }
  75. module.exports = LoaderOptionsPlugin;