AmdLibraryPlugin.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { ConcatSource } = require("webpack-sources");
  7. const ExternalModule = require("../ExternalModule");
  8. const Template = require("../Template");
  9. const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
  10. /** @typedef {import("webpack-sources").Source} Source */
  11. /** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
  12. /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
  13. /** @typedef {import("../Chunk")} Chunk */
  14. /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
  15. /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
  16. /** @typedef {import("../util/Hash")} Hash */
  17. /**
  18. * @template T
  19. * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
  20. */
  21. /**
  22. * @typedef {object} AmdLibraryPluginOptions
  23. * @property {LibraryType} type
  24. * @property {boolean=} requireAsWrapper
  25. */
  26. /**
  27. * @typedef {object} AmdLibraryPluginParsed
  28. * @property {string} name
  29. * @property {string} amdContainer
  30. */
  31. /**
  32. * @typedef {AmdLibraryPluginParsed} T
  33. * @extends {AbstractLibraryPlugin<AmdLibraryPluginParsed>}
  34. */
  35. class AmdLibraryPlugin extends AbstractLibraryPlugin {
  36. /**
  37. * @param {AmdLibraryPluginOptions} options the plugin options
  38. */
  39. constructor(options) {
  40. super({
  41. pluginName: "AmdLibraryPlugin",
  42. type: options.type
  43. });
  44. /** @type {AmdLibraryPluginOptions["requireAsWrapper"]} */
  45. this.requireAsWrapper = options.requireAsWrapper;
  46. }
  47. /**
  48. * @param {LibraryOptions} library normalized library option
  49. * @returns {T} preprocess as needed by overriding
  50. */
  51. parseOptions(library) {
  52. const { name, amdContainer } = library;
  53. if (this.requireAsWrapper) {
  54. if (name) {
  55. throw new Error(
  56. `AMD library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
  57. );
  58. }
  59. } else if (name && typeof name !== "string") {
  60. throw new Error(
  61. `AMD library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
  62. );
  63. }
  64. const _name = /** @type {string} */ (name);
  65. const _amdContainer = /** @type {string} */ (amdContainer);
  66. return { name: _name, amdContainer: _amdContainer };
  67. }
  68. /**
  69. * @param {Source} source source
  70. * @param {RenderContext} renderContext render context
  71. * @param {LibraryContext<T>} libraryContext context
  72. * @returns {Source} source with library export
  73. */
  74. render(
  75. source,
  76. { chunkGraph, chunk, runtimeTemplate },
  77. { options, compilation }
  78. ) {
  79. const modern = runtimeTemplate.supportsArrowFunction();
  80. const modules = chunkGraph
  81. .getChunkModules(chunk)
  82. .filter(
  83. (m) =>
  84. m instanceof ExternalModule &&
  85. (m.externalType === "amd" || m.externalType === "amd-require")
  86. );
  87. const externals = /** @type {ExternalModule[]} */ (modules);
  88. const externalsDepsArray = JSON.stringify(
  89. externals.map((m) =>
  90. typeof m.request === "object" && !Array.isArray(m.request)
  91. ? m.request.amd
  92. : m.request
  93. )
  94. );
  95. const externalsArguments = externals
  96. .map(
  97. (m) =>
  98. `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
  99. `${chunkGraph.getModuleId(m)}`
  100. )}__`
  101. )
  102. .join(", ");
  103. const iife = runtimeTemplate.isIIFE();
  104. const fnStart =
  105. (modern
  106. ? `(${externalsArguments}) => {`
  107. : `function(${externalsArguments}) {`) +
  108. (iife || !chunk.hasRuntime() ? " return " : "\n");
  109. const fnEnd = iife ? ";\n}" : "\n}";
  110. let amdContainerPrefix = "";
  111. if (options.amdContainer) {
  112. amdContainerPrefix = `${options.amdContainer}.`;
  113. }
  114. if (this.requireAsWrapper) {
  115. return new ConcatSource(
  116. `${amdContainerPrefix}require(${externalsDepsArray}, ${fnStart}`,
  117. source,
  118. `${fnEnd});`
  119. );
  120. } else if (options.name) {
  121. const name = compilation.getPath(options.name, {
  122. chunk
  123. });
  124. return new ConcatSource(
  125. `${amdContainerPrefix}define(${JSON.stringify(
  126. name
  127. )}, ${externalsDepsArray}, ${fnStart}`,
  128. source,
  129. `${fnEnd});`
  130. );
  131. } else if (externalsArguments) {
  132. return new ConcatSource(
  133. `${amdContainerPrefix}define(${externalsDepsArray}, ${fnStart}`,
  134. source,
  135. `${fnEnd});`
  136. );
  137. }
  138. return new ConcatSource(
  139. `${amdContainerPrefix}define(${fnStart}`,
  140. source,
  141. `${fnEnd});`
  142. );
  143. }
  144. /**
  145. * @param {Chunk} chunk the chunk
  146. * @param {Hash} hash hash
  147. * @param {ChunkHashContext} chunkHashContext chunk hash context
  148. * @param {LibraryContext<T>} libraryContext context
  149. * @returns {void}
  150. */
  151. chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
  152. hash.update("AmdLibraryPlugin");
  153. if (this.requireAsWrapper) {
  154. hash.update("requireAsWrapper");
  155. } else if (options.name) {
  156. hash.update("named");
  157. const name = compilation.getPath(options.name, {
  158. chunk
  159. });
  160. hash.update(name);
  161. } else if (options.amdContainer) {
  162. hash.update("amdContainer");
  163. hash.update(options.amdContainer);
  164. }
  165. }
  166. }
  167. module.exports = AmdLibraryPlugin;