ExternalModule.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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(${moduleName})${objectLookup};`;
  64. }
  65. checkExternalVariable(variableToCheck, request) {
  66. return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode(
  67. request
  68. )}}\n`;
  69. }
  70. getSourceForAmdOrUmdExternal(id, optional, request) {
  71. const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
  72. `${id}`
  73. )}__`;
  74. const missingModuleError = optional
  75. ? this.checkExternalVariable(externalVariable, request)
  76. : "";
  77. return `${missingModuleError}module.exports = ${externalVariable};`;
  78. }
  79. getSourceForDefaultCase(optional, request) {
  80. const missingModuleError = optional
  81. ? this.checkExternalVariable(request, request)
  82. : "";
  83. return `${missingModuleError}module.exports = ${request};`;
  84. }
  85. getSourceString(runtime) {
  86. const request =
  87. typeof this.request === "object"
  88. ? this.request[this.externalType]
  89. : this.request;
  90. switch (this.externalType) {
  91. case "this":
  92. case "window":
  93. case "self":
  94. return this.getSourceForGlobalVariableExternal(
  95. request,
  96. this.externalType
  97. );
  98. case "global":
  99. return this.getSourceForGlobalVariableExternal(
  100. runtime.outputOptions.globalObject,
  101. this.externalType
  102. );
  103. case "commonjs":
  104. case "commonjs2":
  105. return this.getSourceForCommonJsExternal(request);
  106. case "amd":
  107. case "umd":
  108. case "umd2":
  109. return this.getSourceForAmdOrUmdExternal(
  110. this.id,
  111. this.optional,
  112. request
  113. );
  114. default:
  115. return this.getSourceForDefaultCase(this.optional, request);
  116. }
  117. }
  118. getSource(sourceString) {
  119. if (this.useSourceMap) {
  120. return new OriginalSource(sourceString, this.identifier());
  121. }
  122. return new RawSource(sourceString);
  123. }
  124. source(dependencyTemplates, runtime) {
  125. return this.getSource(this.getSourceString(runtime));
  126. }
  127. size() {
  128. return 42;
  129. }
  130. /**
  131. * @param {Hash} hash the hash used to track dependencies
  132. * @returns {void}
  133. */
  134. updateHash(hash) {
  135. hash.update(this.externalType);
  136. hash.update(JSON.stringify(this.request));
  137. hash.update(JSON.stringify(Boolean(this.optional)));
  138. super.updateHash(hash);
  139. }
  140. }
  141. module.exports = ExternalModule;