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.

179 lines
4.3 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 { OriginalSource, RawSource } = require("webpack-sources");
  7. const Module = require("./Module");
  8. const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
  9. const Template = require("./Template");
  10. /** @typedef {import("./util/createHash").Hash} Hash */
  11. class ExternalModule extends Module {
  12. constructor(request, type, userRequest) {
  13. super("javascript/dynamic", null);
  14. // Info from Factory
  15. this.request = request;
  16. this.externalType = type;
  17. this.userRequest = userRequest;
  18. this.external = true;
  19. }
  20. libIdent() {
  21. return this.userRequest;
  22. }
  23. chunkCondition(chunk) {
  24. return chunk.hasEntryModule();
  25. }
  26. identifier() {
  27. return "external " + JSON.stringify(this.request);
  28. }
  29. readableIdentifier() {
  30. return "external " + JSON.stringify(this.request);
  31. }
  32. needRebuild() {
  33. return false;
  34. }
  35. build(options, compilation, resolver, fs, callback) {
  36. this.built = true;
  37. this.buildMeta = {};
  38. this.buildInfo = {};
  39. callback();
  40. }
  41. getSourceForGlobalVariableExternal(variableName, type) {
  42. if (!Array.isArray(variableName)) {
  43. // make it an array as the look up works the same basically
  44. variableName = [variableName];
  45. }
  46. // needed for e.g. window["some"]["thing"]
  47. const objectLookup = variableName
  48. .map(r => `[${JSON.stringify(r)}]`)
  49. .join("");
  50. return `(function() { module.exports = ${type}${objectLookup}; }());`;
  51. }
  52. getSourceForCommonJsExternal(moduleAndSpecifiers) {
  53. if (!Array.isArray(moduleAndSpecifiers)) {
  54. return `module.exports = require(${JSON.stringify(
  55. moduleAndSpecifiers
  56. )});`;
  57. }
  58. const moduleName = moduleAndSpecifiers[0];
  59. const objectLookup = moduleAndSpecifiers
  60. .slice(1)
  61. .map(r => `[${JSON.stringify(r)}]`)
  62. .join("");
  63. return `module.exports = require(${JSON.stringify(
  64. moduleName
  65. )})${objectLookup};`;
  66. }
  67. checkExternalVariable(variableToCheck, request) {
  68. return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode(
  69. request
  70. )}}\n`;
  71. }
  72. getSourceForAmdOrUmdExternal(id, optional, request) {
  73. const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
  74. `${id}`
  75. )}__`;
  76. const missingModuleError = optional
  77. ? this.checkExternalVariable(externalVariable, request)
  78. : "";
  79. return `${missingModuleError}module.exports = ${externalVariable};`;
  80. }
  81. getSourceForDefaultCase(optional, request) {
  82. if (!Array.isArray(request)) {
  83. // make it an array as the look up works the same basically
  84. request = [request];
  85. }
  86. const variableName = request[0];
  87. const missingModuleError = optional
  88. ? this.checkExternalVariable(variableName, request.join("."))
  89. : "";
  90. const objectLookup = request
  91. .slice(1)
  92. .map(r => `[${JSON.stringify(r)}]`)
  93. .join("");
  94. return `${missingModuleError}module.exports = ${variableName}${objectLookup};`;
  95. }
  96. getSourceString(runtime) {
  97. const request =
  98. typeof this.request === "object" && !Array.isArray(this.request)
  99. ? this.request[this.externalType]
  100. : this.request;
  101. switch (this.externalType) {
  102. case "this":
  103. case "window":
  104. case "self":
  105. return this.getSourceForGlobalVariableExternal(
  106. request,
  107. this.externalType
  108. );
  109. case "global":
  110. return this.getSourceForGlobalVariableExternal(
  111. request,
  112. runtime.outputOptions.globalObject
  113. );
  114. case "commonjs":
  115. case "commonjs2":
  116. return this.getSourceForCommonJsExternal(request);
  117. case "amd":
  118. case "amd-require":
  119. case "umd":
  120. case "umd2":
  121. case "system":
  122. return this.getSourceForAmdOrUmdExternal(
  123. this.id,
  124. this.optional,
  125. request
  126. );
  127. default:
  128. return this.getSourceForDefaultCase(this.optional, request);
  129. }
  130. }
  131. getSource(sourceString) {
  132. if (this.useSourceMap) {
  133. return new OriginalSource(sourceString, this.identifier());
  134. }
  135. return new RawSource(sourceString);
  136. }
  137. source(dependencyTemplates, runtime) {
  138. return this.getSource(this.getSourceString(runtime));
  139. }
  140. size() {
  141. return 42;
  142. }
  143. /**
  144. * @param {Hash} hash the hash used to track dependencies
  145. * @returns {void}
  146. */
  147. updateHash(hash) {
  148. hash.update(this.externalType);
  149. hash.update(JSON.stringify(this.request));
  150. hash.update(JSON.stringify(Boolean(this.optional)));
  151. super.updateHash(hash);
  152. }
  153. }
  154. module.exports = ExternalModule;