ContextReplacementPlugin.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const ContextElementDependency = require("./dependencies/ContextElementDependency");
  7. const { join } = require("./util/fs");
  8. class ContextReplacementPlugin {
  9. constructor(
  10. resourceRegExp,
  11. newContentResource,
  12. newContentRecursive,
  13. newContentRegExp
  14. ) {
  15. this.resourceRegExp = resourceRegExp;
  16. if (typeof newContentResource === "function") {
  17. this.newContentCallback = newContentResource;
  18. } else if (
  19. typeof newContentResource === "string" &&
  20. typeof newContentRecursive === "object"
  21. ) {
  22. this.newContentResource = newContentResource;
  23. this.newContentCreateContextMap = (fs, callback) => {
  24. callback(null, newContentRecursive);
  25. };
  26. } else if (
  27. typeof newContentResource === "string" &&
  28. typeof newContentRecursive === "function"
  29. ) {
  30. this.newContentResource = newContentResource;
  31. this.newContentCreateContextMap = newContentRecursive;
  32. } else {
  33. if (typeof newContentResource !== "string") {
  34. newContentRegExp = newContentRecursive;
  35. newContentRecursive = newContentResource;
  36. newContentResource = undefined;
  37. }
  38. if (typeof newContentRecursive !== "boolean") {
  39. newContentRegExp = newContentRecursive;
  40. newContentRecursive = undefined;
  41. }
  42. this.newContentResource = newContentResource;
  43. this.newContentRecursive = newContentRecursive;
  44. this.newContentRegExp = newContentRegExp;
  45. }
  46. }
  47. apply(compiler) {
  48. const resourceRegExp = this.resourceRegExp;
  49. const newContentCallback = this.newContentCallback;
  50. const newContentResource = this.newContentResource;
  51. const newContentRecursive = this.newContentRecursive;
  52. const newContentRegExp = this.newContentRegExp;
  53. const newContentCreateContextMap = this.newContentCreateContextMap;
  54. compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", cmf => {
  55. cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", result => {
  56. if (!result) return;
  57. if (resourceRegExp.test(result.request)) {
  58. if (newContentResource !== undefined) {
  59. result.request = newContentResource;
  60. }
  61. if (newContentRecursive !== undefined) {
  62. result.recursive = newContentRecursive;
  63. }
  64. if (newContentRegExp !== undefined) {
  65. result.regExp = newContentRegExp;
  66. }
  67. if (typeof newContentCallback === "function") {
  68. newContentCallback(result);
  69. } else {
  70. for (const d of result.dependencies) {
  71. if (d.critical) d.critical = false;
  72. }
  73. }
  74. }
  75. return result;
  76. });
  77. cmf.hooks.afterResolve.tap("ContextReplacementPlugin", result => {
  78. if (!result) return;
  79. if (resourceRegExp.test(result.resource)) {
  80. if (newContentResource !== undefined) {
  81. if (
  82. newContentResource.startsWith("/") ||
  83. (newContentResource.length > 1 && newContentResource[1] === ":")
  84. ) {
  85. result.resource = newContentResource;
  86. } else {
  87. result.resource = join(
  88. compiler.inputFileSystem,
  89. result.resource,
  90. newContentResource
  91. );
  92. }
  93. }
  94. if (newContentRecursive !== undefined) {
  95. result.recursive = newContentRecursive;
  96. }
  97. if (newContentRegExp !== undefined) {
  98. result.regExp = newContentRegExp;
  99. }
  100. if (typeof newContentCreateContextMap === "function") {
  101. result.resolveDependencies =
  102. createResolveDependenciesFromContextMap(
  103. newContentCreateContextMap
  104. );
  105. }
  106. if (typeof newContentCallback === "function") {
  107. const origResource = result.resource;
  108. newContentCallback(result);
  109. if (
  110. result.resource !== origResource &&
  111. !result.resource.startsWith("/") &&
  112. (result.resource.length <= 1 || result.resource[1] !== ":")
  113. ) {
  114. // When the function changed it to an relative path
  115. result.resource = join(
  116. compiler.inputFileSystem,
  117. origResource,
  118. result.resource
  119. );
  120. }
  121. } else {
  122. for (const d of result.dependencies) {
  123. if (d.critical) d.critical = false;
  124. }
  125. }
  126. }
  127. return result;
  128. });
  129. });
  130. }
  131. }
  132. const createResolveDependenciesFromContextMap = createContextMap => {
  133. const resolveDependenciesFromContextMap = (fs, options, callback) => {
  134. createContextMap(fs, (err, map) => {
  135. if (err) return callback(err);
  136. const dependencies = Object.keys(map).map(key => {
  137. return new ContextElementDependency(
  138. map[key] + options.resourceQuery + options.resourceFragment,
  139. key,
  140. options.category,
  141. options.referencedExports
  142. );
  143. });
  144. callback(null, dependencies);
  145. });
  146. };
  147. return resolveDependenciesFromContextMap;
  148. };
  149. module.exports = ContextReplacementPlugin;