10
0

AmdLibraryPlugin.js 4.9 KB

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