| 1 | /*
|
|---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
|---|
| 3 | Author Tobias Koppers @sokra
|
|---|
| 4 | */
|
|---|
| 5 |
|
|---|
| 6 | "use strict";
|
|---|
| 7 |
|
|---|
| 8 | const { ConcatSource, OriginalSource } = require("webpack-sources");
|
|---|
| 9 | const ExternalModule = require("../ExternalModule");
|
|---|
| 10 | const Template = require("../Template");
|
|---|
| 11 | const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
|
|---|
| 12 |
|
|---|
| 13 | /** @typedef {import("webpack-sources").Source} Source */
|
|---|
| 14 | /** @typedef {import("../../declarations/WebpackOptions").LibraryCustomUmdCommentObject} LibraryCustomUmdCommentObject */
|
|---|
| 15 | /** @typedef {import("../../declarations/WebpackOptions").LibraryCustomUmdObject} LibraryCustomUmdObject */
|
|---|
| 16 | /** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
|
|---|
| 17 | /** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
|
|---|
| 18 | /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
|
|---|
| 19 | /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
|
|---|
| 20 | /** @typedef {import("../ExternalModule").RequestRecord} RequestRecord */
|
|---|
| 21 |
|
|---|
| 22 | /**
|
|---|
| 23 | * Defines the shared type used by this module.
|
|---|
| 24 | * @template T
|
|---|
| 25 | * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
|
|---|
| 26 | */
|
|---|
| 27 |
|
|---|
| 28 | /**
|
|---|
| 29 | * Accessor to object access.
|
|---|
| 30 | * @param {string[]} accessor the accessor to convert to path
|
|---|
| 31 | * @returns {string} the path
|
|---|
| 32 | */
|
|---|
| 33 | const accessorToObjectAccess = (accessor) =>
|
|---|
| 34 | accessor.map((a) => `[${JSON.stringify(a)}]`).join("");
|
|---|
| 35 |
|
|---|
| 36 | /** @typedef {string | string[]} Accessor */
|
|---|
| 37 |
|
|---|
| 38 | /**
|
|---|
| 39 | * Returns the path.
|
|---|
| 40 | * @param {string | undefined} base the path prefix
|
|---|
| 41 | * @param {Accessor} accessor the accessor
|
|---|
| 42 | * @param {string=} joinWith the element separator
|
|---|
| 43 | * @returns {string} the path
|
|---|
| 44 | */
|
|---|
| 45 | const accessorAccess = (base, accessor, joinWith = ", ") => {
|
|---|
| 46 | const accessors = Array.isArray(accessor) ? accessor : [accessor];
|
|---|
| 47 | return accessors
|
|---|
| 48 | .map((_, idx) => {
|
|---|
| 49 | const a = base
|
|---|
| 50 | ? base + accessorToObjectAccess(accessors.slice(0, idx + 1))
|
|---|
| 51 | : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1));
|
|---|
| 52 | if (idx === accessors.length - 1) return a;
|
|---|
| 53 | if (idx === 0 && base === undefined) {
|
|---|
| 54 | return `${a} = typeof ${a} === "object" ? ${a} : {}`;
|
|---|
| 55 | }
|
|---|
| 56 | return `${a} = ${a} || {}`;
|
|---|
| 57 | })
|
|---|
| 58 | .join(joinWith);
|
|---|
| 59 | };
|
|---|
| 60 |
|
|---|
| 61 | /**
|
|---|
| 62 | * Defines the umd library plugin options type used by this module.
|
|---|
| 63 | * @typedef {object} UmdLibraryPluginOptions
|
|---|
| 64 | * @property {LibraryType} type
|
|---|
| 65 | * @property {boolean=} optionalAmdExternalAsGlobal
|
|---|
| 66 | */
|
|---|
| 67 |
|
|---|
| 68 | /**
|
|---|
| 69 | * Defines the umd library plugin parsed type used by this module.
|
|---|
| 70 | * @typedef {object} UmdLibraryPluginParsed
|
|---|
| 71 | * @property {string | string[] | undefined} name
|
|---|
| 72 | * @property {LibraryCustomUmdObject} names
|
|---|
| 73 | * @property {string | LibraryCustomUmdCommentObject | undefined} auxiliaryComment
|
|---|
| 74 | * @property {boolean | undefined} namedDefine
|
|---|
| 75 | */
|
|---|
| 76 |
|
|---|
| 77 | /**
|
|---|
| 78 | * Represents the umd library plugin runtime component.
|
|---|
| 79 | * @typedef {UmdLibraryPluginParsed} T
|
|---|
| 80 | * @extends {AbstractLibraryPlugin<UmdLibraryPluginParsed>}
|
|---|
| 81 | */
|
|---|
| 82 | class UmdLibraryPlugin extends AbstractLibraryPlugin {
|
|---|
| 83 | /**
|
|---|
| 84 | * Creates an instance of UmdLibraryPlugin.
|
|---|
| 85 | * @param {UmdLibraryPluginOptions} options the plugin option
|
|---|
| 86 | */
|
|---|
| 87 | constructor(options) {
|
|---|
| 88 | super({
|
|---|
| 89 | pluginName: "UmdLibraryPlugin",
|
|---|
| 90 | type: options.type
|
|---|
| 91 | });
|
|---|
| 92 |
|
|---|
| 93 | /** @type {UmdLibraryPluginOptions["optionalAmdExternalAsGlobal"]} */
|
|---|
| 94 | this.optionalAmdExternalAsGlobal = options.optionalAmdExternalAsGlobal;
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | /**
|
|---|
| 98 | * Returns preprocess as needed by overriding.
|
|---|
| 99 | * @param {LibraryOptions} library normalized library option
|
|---|
| 100 | * @returns {T} preprocess as needed by overriding
|
|---|
| 101 | */
|
|---|
| 102 | parseOptions(library) {
|
|---|
| 103 | /** @type {LibraryName | undefined} */
|
|---|
| 104 | let name;
|
|---|
| 105 | /** @type {LibraryCustomUmdObject} */
|
|---|
| 106 | let names;
|
|---|
| 107 | if (typeof library.name === "object" && !Array.isArray(library.name)) {
|
|---|
| 108 | name = library.name.root || library.name.amd || library.name.commonjs;
|
|---|
| 109 | names = library.name;
|
|---|
| 110 | } else {
|
|---|
| 111 | name = library.name;
|
|---|
| 112 | const singleName = Array.isArray(name) ? name[0] : name;
|
|---|
| 113 | names = {
|
|---|
| 114 | commonjs: singleName,
|
|---|
| 115 | root: library.name,
|
|---|
| 116 | amd: singleName
|
|---|
| 117 | };
|
|---|
| 118 | }
|
|---|
| 119 | return {
|
|---|
| 120 | name,
|
|---|
| 121 | names,
|
|---|
| 122 | auxiliaryComment: library.auxiliaryComment,
|
|---|
| 123 | namedDefine: library.umdNamedDefine
|
|---|
| 124 | };
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 | /**
|
|---|
| 128 | * Returns source with library export.
|
|---|
| 129 | * @param {Source} source source
|
|---|
| 130 | * @param {RenderContext} renderContext render context
|
|---|
| 131 | * @param {LibraryContext<T>} libraryContext context
|
|---|
| 132 | * @returns {Source} source with library export
|
|---|
| 133 | */
|
|---|
| 134 | render(
|
|---|
| 135 | source,
|
|---|
| 136 | { chunkGraph, runtimeTemplate, chunk, moduleGraph },
|
|---|
| 137 | { options, compilation }
|
|---|
| 138 | ) {
|
|---|
| 139 | const modules = chunkGraph
|
|---|
| 140 | .getChunkModules(chunk)
|
|---|
| 141 | .filter(
|
|---|
| 142 | (m) =>
|
|---|
| 143 | m instanceof ExternalModule &&
|
|---|
| 144 | (m.externalType === "umd" || m.externalType === "umd2")
|
|---|
| 145 | );
|
|---|
| 146 | let externals = /** @type {ExternalModule[]} */ (modules);
|
|---|
| 147 | /** @type {ExternalModule[]} */
|
|---|
| 148 | const optionalExternals = [];
|
|---|
| 149 | /** @type {ExternalModule[]} */
|
|---|
| 150 | let requiredExternals = [];
|
|---|
| 151 | if (this.optionalAmdExternalAsGlobal) {
|
|---|
| 152 | for (const m of externals) {
|
|---|
| 153 | if (m.isOptional(moduleGraph)) {
|
|---|
| 154 | optionalExternals.push(m);
|
|---|
| 155 | } else {
|
|---|
| 156 | requiredExternals.push(m);
|
|---|
| 157 | }
|
|---|
| 158 | }
|
|---|
| 159 | externals = [...requiredExternals, ...optionalExternals];
|
|---|
| 160 | } else {
|
|---|
| 161 | requiredExternals = externals;
|
|---|
| 162 | }
|
|---|
| 163 |
|
|---|
| 164 | /**
|
|---|
| 165 | * Returns the replaced keys.
|
|---|
| 166 | * @param {string} str the string to replace
|
|---|
| 167 | * @returns {string} the replaced keys
|
|---|
| 168 | */
|
|---|
| 169 | const replaceKeys = (str) =>
|
|---|
| 170 | compilation.getPath(str, {
|
|---|
| 171 | chunk
|
|---|
| 172 | });
|
|---|
| 173 |
|
|---|
| 174 | /**
|
|---|
| 175 | * Externals deps array.
|
|---|
| 176 | * @param {ExternalModule[]} modules external modules
|
|---|
| 177 | * @returns {string} result
|
|---|
| 178 | */
|
|---|
| 179 | const externalsDepsArray = (modules) =>
|
|---|
| 180 | `[${replaceKeys(
|
|---|
| 181 | modules
|
|---|
| 182 | .map((m) =>
|
|---|
| 183 | JSON.stringify(
|
|---|
| 184 | typeof m.request === "object"
|
|---|
| 185 | ? /** @type {RequestRecord} */
|
|---|
| 186 | (m.request).amd
|
|---|
| 187 | : m.request
|
|---|
| 188 | )
|
|---|
| 189 | )
|
|---|
| 190 | .join(", ")
|
|---|
| 191 | )}]`;
|
|---|
| 192 |
|
|---|
| 193 | /**
|
|---|
| 194 | * Externals root array.
|
|---|
| 195 | * @param {ExternalModule[]} modules external modules
|
|---|
| 196 | * @returns {string} result
|
|---|
| 197 | */
|
|---|
| 198 | const externalsRootArray = (modules) =>
|
|---|
| 199 | replaceKeys(
|
|---|
| 200 | modules
|
|---|
| 201 | .map((m) => {
|
|---|
| 202 | let request = m.request;
|
|---|
| 203 | if (typeof request === "object") {
|
|---|
| 204 | request =
|
|---|
| 205 | /** @type {RequestRecord} */
|
|---|
| 206 | (request).root;
|
|---|
| 207 | }
|
|---|
| 208 | return `root${accessorToObjectAccess([
|
|---|
| 209 | ...(Array.isArray(request) ? request : [request])
|
|---|
| 210 | ])}`;
|
|---|
| 211 | })
|
|---|
| 212 | .join(", ")
|
|---|
| 213 | );
|
|---|
| 214 |
|
|---|
| 215 | /**
|
|---|
| 216 | * Externals require array.
|
|---|
| 217 | * @param {string} type the type
|
|---|
| 218 | * @returns {string} external require array
|
|---|
| 219 | */
|
|---|
| 220 | const externalsRequireArray = (type) =>
|
|---|
| 221 | replaceKeys(
|
|---|
| 222 | externals
|
|---|
| 223 | .map((m) => {
|
|---|
| 224 | let request = m.request;
|
|---|
| 225 | if (typeof request === "object") {
|
|---|
| 226 | request =
|
|---|
| 227 | /** @type {RequestRecord} */
|
|---|
| 228 | (request)[type];
|
|---|
| 229 | }
|
|---|
| 230 | if (request === undefined) {
|
|---|
| 231 | throw new Error(
|
|---|
| 232 | `Missing external configuration for type:${type}`
|
|---|
| 233 | );
|
|---|
| 234 | }
|
|---|
| 235 | let expr = Array.isArray(request)
|
|---|
| 236 | ? `require(${JSON.stringify(
|
|---|
| 237 | request[0]
|
|---|
| 238 | )})${accessorToObjectAccess(request.slice(1))}`
|
|---|
| 239 | : `require(${JSON.stringify(request)})`;
|
|---|
| 240 | if (m.isOptional(moduleGraph)) {
|
|---|
| 241 | expr = `(function webpackLoadOptionalExternalModule() { try { return ${expr}; } catch(e) {} }())`;
|
|---|
| 242 | }
|
|---|
| 243 | return expr;
|
|---|
| 244 | })
|
|---|
| 245 | .join(", ")
|
|---|
| 246 | );
|
|---|
| 247 |
|
|---|
| 248 | /**
|
|---|
| 249 | * Externals arguments.
|
|---|
| 250 | * @param {ExternalModule[]} modules external modules
|
|---|
| 251 | * @returns {string} arguments
|
|---|
| 252 | */
|
|---|
| 253 | const externalsArguments = (modules) =>
|
|---|
| 254 | modules
|
|---|
| 255 | .map(
|
|---|
| 256 | (m) =>
|
|---|
| 257 | `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
|
|---|
| 258 | `${chunkGraph.getModuleId(m)}`
|
|---|
| 259 | )}__`
|
|---|
| 260 | )
|
|---|
| 261 | .join(", ");
|
|---|
| 262 |
|
|---|
| 263 | /**
|
|---|
| 264 | * Returns stringified library name.
|
|---|
| 265 | * @param {Accessor} library library name
|
|---|
| 266 | * @returns {string} stringified library name
|
|---|
| 267 | */
|
|---|
| 268 | const libraryName = (library) =>
|
|---|
| 269 | JSON.stringify(
|
|---|
| 270 | replaceKeys(
|
|---|
| 271 | /** @type {string} */
|
|---|
| 272 | ([...(Array.isArray(library) ? library : [library])].pop())
|
|---|
| 273 | )
|
|---|
| 274 | );
|
|---|
| 275 |
|
|---|
| 276 | /** @type {string} */
|
|---|
| 277 | let amdFactory;
|
|---|
| 278 | if (optionalExternals.length > 0) {
|
|---|
| 279 | const wrapperArguments = externalsArguments(requiredExternals);
|
|---|
| 280 | const factoryArguments =
|
|---|
| 281 | requiredExternals.length > 0
|
|---|
| 282 | ? `${externalsArguments(requiredExternals)}, ${externalsRootArray(
|
|---|
| 283 | optionalExternals
|
|---|
| 284 | )}`
|
|---|
| 285 | : externalsRootArray(optionalExternals);
|
|---|
| 286 | amdFactory =
|
|---|
| 287 | `function webpackLoadOptionalExternalModuleAmd(${wrapperArguments}) {\n` +
|
|---|
| 288 | ` return factory(${factoryArguments});\n` +
|
|---|
| 289 | " }";
|
|---|
| 290 | } else {
|
|---|
| 291 | amdFactory = "factory";
|
|---|
| 292 | }
|
|---|
| 293 |
|
|---|
| 294 | const { auxiliaryComment, namedDefine, names } = options;
|
|---|
| 295 |
|
|---|
| 296 | /**
|
|---|
| 297 | * Gets auxiliary comment.
|
|---|
| 298 | * @param {keyof LibraryCustomUmdCommentObject} type type
|
|---|
| 299 | * @returns {string} comment
|
|---|
| 300 | */
|
|---|
| 301 | const getAuxiliaryComment = (type) => {
|
|---|
| 302 | if (auxiliaryComment) {
|
|---|
| 303 | if (typeof auxiliaryComment === "string") {
|
|---|
| 304 | return `\t//${auxiliaryComment}\n`;
|
|---|
| 305 | }
|
|---|
| 306 | if (auxiliaryComment[type]) return `\t//${auxiliaryComment[type]}\n`;
|
|---|
| 307 | }
|
|---|
| 308 | return "";
|
|---|
| 309 | };
|
|---|
| 310 |
|
|---|
| 311 | return new ConcatSource(
|
|---|
| 312 | new OriginalSource(
|
|---|
| 313 | `(function webpackUniversalModuleDefinition(root, factory) {\n${getAuxiliaryComment(
|
|---|
| 314 | "commonjs2"
|
|---|
| 315 | )} if(typeof exports === 'object' && typeof module === 'object')\n` +
|
|---|
| 316 | ` module.exports = factory(${externalsRequireArray(
|
|---|
| 317 | "commonjs2"
|
|---|
| 318 | )});\n${getAuxiliaryComment(
|
|---|
| 319 | "amd"
|
|---|
| 320 | )} else if(typeof define === 'function' && define.amd)\n${
|
|---|
| 321 | requiredExternals.length > 0
|
|---|
| 322 | ? names.amd && namedDefine === true
|
|---|
| 323 | ? ` define(${libraryName(names.amd)}, ${externalsDepsArray(
|
|---|
| 324 | requiredExternals
|
|---|
| 325 | )}, ${amdFactory});\n`
|
|---|
| 326 | : ` define(${externalsDepsArray(requiredExternals)}, ${
|
|---|
| 327 | amdFactory
|
|---|
| 328 | });\n`
|
|---|
| 329 | : names.amd && namedDefine === true
|
|---|
| 330 | ? ` define(${libraryName(names.amd)}, [], ${amdFactory});\n`
|
|---|
| 331 | : ` define([], ${amdFactory});\n`
|
|---|
| 332 | }${
|
|---|
| 333 | names.root || names.commonjs
|
|---|
| 334 | ? `${getAuxiliaryComment(
|
|---|
| 335 | "commonjs"
|
|---|
| 336 | )} else if(typeof exports === 'object')\n` +
|
|---|
| 337 | ` exports[${libraryName(
|
|---|
| 338 | /** @type {Accessor} */
|
|---|
| 339 | (names.commonjs || names.root)
|
|---|
| 340 | )}] = factory(${externalsRequireArray(
|
|---|
| 341 | "commonjs"
|
|---|
| 342 | )});\n${getAuxiliaryComment("root")} else\n` +
|
|---|
| 343 | ` ${replaceKeys(
|
|---|
| 344 | accessorAccess(
|
|---|
| 345 | "root",
|
|---|
| 346 | /** @type {Accessor} */
|
|---|
| 347 | (names.root || names.commonjs)
|
|---|
| 348 | )
|
|---|
| 349 | )} = factory(${externalsRootArray(externals)});\n`
|
|---|
| 350 | : ` else {\n${
|
|---|
| 351 | externals.length > 0
|
|---|
| 352 | ? ` var a = typeof exports === 'object' ? factory(${externalsRequireArray(
|
|---|
| 353 | "commonjs"
|
|---|
| 354 | )}) : factory(${externalsRootArray(externals)});\n`
|
|---|
| 355 | : " var a = factory();\n"
|
|---|
| 356 | } for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n` +
|
|---|
| 357 | " }\n"
|
|---|
| 358 | }})(${runtimeTemplate.globalObject}, ${
|
|---|
| 359 | runtimeTemplate.supportsArrowFunction()
|
|---|
| 360 | ? `(${externalsArguments(externals)}) =>`
|
|---|
| 361 | : `function(${externalsArguments(externals)})`
|
|---|
| 362 | } {\nreturn `,
|
|---|
| 363 | "webpack/universalModuleDefinition"
|
|---|
| 364 | ),
|
|---|
| 365 | source,
|
|---|
| 366 | ";\n})"
|
|---|
| 367 | );
|
|---|
| 368 | }
|
|---|
| 369 | }
|
|---|
| 370 |
|
|---|
| 371 | module.exports = UmdLibraryPlugin;
|
|---|