You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.8 KiB

4 years ago
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RequireContextDependency = require("./RequireContextDependency");
  7. const ContextElementDependency = require("./ContextElementDependency");
  8. const RequireContextDependencyParserPlugin = require("./RequireContextDependencyParserPlugin");
  9. class RequireContextPlugin {
  10. constructor(modulesDirectories, extensions, mainFiles) {
  11. if (!Array.isArray(modulesDirectories)) {
  12. throw new Error("modulesDirectories must be an array");
  13. }
  14. if (!Array.isArray(extensions)) {
  15. throw new Error("extensions must be an array");
  16. }
  17. this.modulesDirectories = modulesDirectories;
  18. this.extensions = extensions;
  19. this.mainFiles = mainFiles;
  20. }
  21. apply(compiler) {
  22. compiler.hooks.compilation.tap(
  23. "RequireContextPlugin",
  24. (compilation, { contextModuleFactory, normalModuleFactory }) => {
  25. compilation.dependencyFactories.set(
  26. RequireContextDependency,
  27. contextModuleFactory
  28. );
  29. compilation.dependencyTemplates.set(
  30. RequireContextDependency,
  31. new RequireContextDependency.Template()
  32. );
  33. compilation.dependencyFactories.set(
  34. ContextElementDependency,
  35. normalModuleFactory
  36. );
  37. const handler = (parser, parserOptions) => {
  38. if (
  39. parserOptions.requireContext !== undefined &&
  40. !parserOptions.requireContext
  41. )
  42. return;
  43. new RequireContextDependencyParserPlugin().apply(parser);
  44. };
  45. normalModuleFactory.hooks.parser
  46. .for("javascript/auto")
  47. .tap("RequireContextPlugin", handler);
  48. normalModuleFactory.hooks.parser
  49. .for("javascript/dynamic")
  50. .tap("RequireContextPlugin", handler);
  51. contextModuleFactory.hooks.alternatives.tap(
  52. "RequireContextPlugin",
  53. items => {
  54. if (items.length === 0) return items;
  55. return items
  56. .map(obj => {
  57. return this.extensions
  58. .filter(ext => {
  59. const l = obj.request.length;
  60. return (
  61. l > ext.length &&
  62. obj.request.substr(l - ext.length, l) === ext
  63. );
  64. })
  65. .map(ext => {
  66. const l = obj.request.length;
  67. return {
  68. context: obj.context,
  69. request: obj.request.substr(0, l - ext.length)
  70. };
  71. })
  72. .concat(obj);
  73. })
  74. .reduce((a, b) => a.concat(b), []);
  75. }
  76. );
  77. contextModuleFactory.hooks.alternatives.tap(
  78. "RequireContextPlugin",
  79. items => {
  80. if (items.length === 0) return items;
  81. return items
  82. .map(obj => {
  83. return this.mainFiles
  84. .filter(mainFile => {
  85. const l = obj.request.length;
  86. return (
  87. l > mainFile.length + 1 &&
  88. obj.request.substr(l - mainFile.length - 1, l) ===
  89. "/" + mainFile
  90. );
  91. })
  92. .map(mainFile => {
  93. const l = obj.request.length;
  94. return [
  95. {
  96. context: obj.context,
  97. request: obj.request.substr(0, l - mainFile.length)
  98. },
  99. {
  100. context: obj.context,
  101. request: obj.request.substr(0, l - mainFile.length - 1)
  102. }
  103. ];
  104. })
  105. .reduce((a, b) => a.concat(b), [])
  106. .concat(obj);
  107. })
  108. .reduce((a, b) => a.concat(b), []);
  109. }
  110. );
  111. contextModuleFactory.hooks.alternatives.tap(
  112. "RequireContextPlugin",
  113. items => {
  114. if (items.length === 0) return items;
  115. return items.map(obj => {
  116. for (let i = 0; i < this.modulesDirectories.length; i++) {
  117. const dir = this.modulesDirectories[i];
  118. const idx = obj.request.indexOf("./" + dir + "/");
  119. if (idx === 0) {
  120. obj.request = obj.request.slice(dir.length + 3);
  121. break;
  122. }
  123. }
  124. return obj;
  125. });
  126. }
  127. );
  128. }
  129. );
  130. }
  131. }
  132. module.exports = RequireContextPlugin;