LibraryTemplatePlugin.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin");
  7. /** @typedef {import("../declarations/WebpackOptions").LibraryCustomUmdObject} LibraryCustomUmdObject */
  8. /** @typedef {import("./Compiler")} Compiler */
  9. /**
  10. * @param {string[]} accessor the accessor to convert to path
  11. * @returns {string} the path
  12. */
  13. const accessorToObjectAccess = accessor => {
  14. return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
  15. };
  16. /**
  17. * @param {string=} base the path prefix
  18. * @param {string|string[]|LibraryCustomUmdObject} accessor the accessor
  19. * @param {"amd" | "commonjs" | "root"} umdProperty property used when a custom umd object is provided
  20. * @param {string=} joinWith the element separator
  21. * @returns {string} the path
  22. */
  23. const accessorAccess = (base, accessor, umdProperty, joinWith = "; ") => {
  24. const normalizedAccessor =
  25. typeof accessor === "object" && !Array.isArray(accessor)
  26. ? accessor[umdProperty]
  27. : accessor;
  28. const accessors = Array.isArray(normalizedAccessor)
  29. ? normalizedAccessor
  30. : [normalizedAccessor];
  31. return accessors
  32. .map((_, idx) => {
  33. const a = base
  34. ? base + accessorToObjectAccess(accessors.slice(0, idx + 1))
  35. : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1));
  36. if (idx === accessors.length - 1) return a;
  37. if (idx === 0 && base === undefined) {
  38. return `${a} = typeof ${a} === "object" ? ${a} : {}`;
  39. }
  40. return `${a} = ${a} || {}`;
  41. })
  42. .join(joinWith);
  43. };
  44. class LibraryTemplatePlugin {
  45. /**
  46. * @param {string|string[]|LibraryCustomUmdObject} name name of library
  47. * @param {string} target type of library
  48. * @param {boolean} umdNamedDefine setting this to true will name the UMD module
  49. * @param {string|TODO} auxiliaryComment comment in the UMD wrapper
  50. * @param {string|string[]} exportProperty which export should be exposed as library
  51. */
  52. constructor(name, target, umdNamedDefine, auxiliaryComment, exportProperty) {
  53. this.name = name;
  54. this.target = target;
  55. this.umdNamedDefine = umdNamedDefine;
  56. this.auxiliaryComment = auxiliaryComment;
  57. this.exportProperty = exportProperty;
  58. }
  59. /**
  60. * @param {Compiler} compiler the compiler instance
  61. * @returns {void}
  62. */
  63. apply(compiler) {
  64. compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", compilation => {
  65. if (this.exportProperty) {
  66. const ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin");
  67. new ExportPropertyMainTemplatePlugin(this.exportProperty).apply(
  68. compilation
  69. );
  70. }
  71. switch (this.target) {
  72. case "var":
  73. if (
  74. !this.name ||
  75. (typeof this.name === "object" && !Array.isArray(this.name))
  76. ) {
  77. throw new Error(
  78. "library name must be set and not an UMD custom object for non-UMD target"
  79. );
  80. }
  81. new SetVarMainTemplatePlugin(
  82. `var ${accessorAccess(undefined, this.name, "root")}`,
  83. false
  84. ).apply(compilation);
  85. break;
  86. case "assign":
  87. new SetVarMainTemplatePlugin(
  88. accessorAccess(undefined, this.name, "root"),
  89. false
  90. ).apply(compilation);
  91. break;
  92. case "this":
  93. case "self":
  94. case "window":
  95. if (this.name) {
  96. new SetVarMainTemplatePlugin(
  97. accessorAccess(this.target, this.name, "root"),
  98. false
  99. ).apply(compilation);
  100. } else {
  101. new SetVarMainTemplatePlugin(this.target, true).apply(compilation);
  102. }
  103. break;
  104. case "global":
  105. if (this.name) {
  106. new SetVarMainTemplatePlugin(
  107. accessorAccess(
  108. compilation.runtimeTemplate.outputOptions.globalObject,
  109. this.name,
  110. "root"
  111. ),
  112. false
  113. ).apply(compilation);
  114. } else {
  115. new SetVarMainTemplatePlugin(
  116. compilation.runtimeTemplate.outputOptions.globalObject,
  117. true
  118. ).apply(compilation);
  119. }
  120. break;
  121. case "commonjs":
  122. if (this.name) {
  123. new SetVarMainTemplatePlugin(
  124. accessorAccess("exports", this.name, "commonjs"),
  125. false
  126. ).apply(compilation);
  127. } else {
  128. new SetVarMainTemplatePlugin("exports", true).apply(compilation);
  129. }
  130. break;
  131. case "commonjs2":
  132. case "commonjs-module":
  133. new SetVarMainTemplatePlugin("module.exports", false).apply(
  134. compilation
  135. );
  136. break;
  137. case "amd":
  138. case "amd-require": {
  139. const AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin");
  140. if (this.name && typeof this.name !== "string") {
  141. throw new Error("library name must be a string for amd target");
  142. }
  143. new AmdMainTemplatePlugin({
  144. name: this.name,
  145. requireAsWrapper: this.target === "amd-require"
  146. }).apply(compilation);
  147. break;
  148. }
  149. case "umd":
  150. case "umd2": {
  151. const UmdMainTemplatePlugin = require("./UmdMainTemplatePlugin");
  152. new UmdMainTemplatePlugin(this.name, {
  153. optionalAmdExternalAsGlobal: this.target === "umd2",
  154. namedDefine: this.umdNamedDefine,
  155. auxiliaryComment: this.auxiliaryComment
  156. }).apply(compilation);
  157. break;
  158. }
  159. case "jsonp": {
  160. const JsonpExportMainTemplatePlugin = require("./web/JsonpExportMainTemplatePlugin");
  161. if (typeof this.name !== "string")
  162. throw new Error("library name must be a string for jsonp target");
  163. new JsonpExportMainTemplatePlugin(this.name).apply(compilation);
  164. break;
  165. }
  166. case "system": {
  167. const SystemMainTemplatePlugin = require("./SystemMainTemplatePlugin");
  168. new SystemMainTemplatePlugin({
  169. name: this.name
  170. }).apply(compilation);
  171. break;
  172. }
  173. default:
  174. throw new Error(`${this.target} is not a valid Library target`);
  175. }
  176. });
  177. }
  178. }
  179. module.exports = LibraryTemplatePlugin;