AmdLibraryPlugin.js 4.4 KB

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