LoaderOptionsPlugin.js 2.3 KB

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