LoaderPlugin.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const LoaderDependency = require("./LoaderDependency");
  7. const NormalModule = require("../NormalModule");
  8. /** @typedef {import("../Module")} Module */
  9. /**
  10. * @callback LoadModuleCallback
  11. * @param {Error=} err error object
  12. * @param {string=} source source code
  13. * @param {object=} map source map
  14. * @param {Module=} module loaded module if successful
  15. */
  16. class LoaderPlugin {
  17. apply(compiler) {
  18. compiler.hooks.compilation.tap(
  19. "LoaderPlugin",
  20. (compilation, { normalModuleFactory }) => {
  21. compilation.dependencyFactories.set(
  22. LoaderDependency,
  23. normalModuleFactory
  24. );
  25. }
  26. );
  27. compiler.hooks.compilation.tap("LoaderPlugin", compilation => {
  28. compilation.hooks.normalModuleLoader.tap(
  29. "LoaderPlugin",
  30. (loaderContext, module) => {
  31. /**
  32. * @param {string} request the request string to load the module from
  33. * @param {LoadModuleCallback} callback callback returning the loaded module or error
  34. * @returns {void}
  35. */
  36. loaderContext.loadModule = (request, callback) => {
  37. const dep = new LoaderDependency(request);
  38. dep.loc = {
  39. name: request
  40. };
  41. const factory = compilation.dependencyFactories.get(
  42. dep.constructor
  43. );
  44. if (factory === undefined) {
  45. return callback(
  46. new Error(
  47. `No module factory available for dependency type: ${
  48. dep.constructor.name
  49. }`
  50. )
  51. );
  52. }
  53. compilation.semaphore.release();
  54. compilation.addModuleDependencies(
  55. module,
  56. [
  57. {
  58. factory,
  59. dependencies: [dep]
  60. }
  61. ],
  62. true,
  63. "lm",
  64. true,
  65. err => {
  66. compilation.semaphore.acquire(() => {
  67. if (err) {
  68. return callback(err);
  69. }
  70. if (!dep.module) {
  71. return callback(new Error("Cannot load the module"));
  72. }
  73. // TODO consider removing this in webpack 5
  74. if (dep.module instanceof NormalModule && dep.module.error) {
  75. return callback(dep.module.error);
  76. }
  77. if (!dep.module._source) {
  78. throw new Error(
  79. "The module created for a LoaderDependency must have a property _source"
  80. );
  81. }
  82. let source, map;
  83. const moduleSource = dep.module._source;
  84. if (moduleSource.sourceAndMap) {
  85. const sourceAndMap = moduleSource.sourceAndMap();
  86. map = sourceAndMap.map;
  87. source = sourceAndMap.source;
  88. } else {
  89. map = moduleSource.map();
  90. source = moduleSource.source();
  91. }
  92. if (dep.module.buildInfo.fileDependencies) {
  93. for (const d of dep.module.buildInfo.fileDependencies) {
  94. loaderContext.addDependency(d);
  95. }
  96. }
  97. if (dep.module.buildInfo.contextDependencies) {
  98. for (const d of dep.module.buildInfo.contextDependencies) {
  99. loaderContext.addContextDependency(d);
  100. }
  101. }
  102. return callback(null, source, map, dep.module);
  103. });
  104. }
  105. );
  106. };
  107. }
  108. );
  109. });
  110. }
  111. }
  112. module.exports = LoaderPlugin;