diff --git a/lib/AmdMainTemplatePlugin.js b/lib/AmdMainTemplatePlugin.js index 72f23027d9d..b950ed5e08f 100644 --- a/lib/AmdMainTemplatePlugin.js +++ b/lib/AmdMainTemplatePlugin.js @@ -8,11 +8,21 @@ const { ConcatSource } = require("webpack-sources"); const Template = require("./Template"); +/** @typedef {import("./Compilation")} Compilation */ + class AmdMainTemplatePlugin { + /** + * @param {string} name the library name + */ constructor(name) { + /** @type {string} */ this.name = name; } + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ apply(compilation) { const { mainTemplate, chunkTemplate } = compilation; diff --git a/lib/ExportPropertyMainTemplatePlugin.js b/lib/ExportPropertyMainTemplatePlugin.js index 28d119e5f42..90df031aabb 100644 --- a/lib/ExportPropertyMainTemplatePlugin.js +++ b/lib/ExportPropertyMainTemplatePlugin.js @@ -6,15 +6,28 @@ const { ConcatSource } = require("webpack-sources"); +/** @typedef {import("./Compilation")} Compilation */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ const accessorToObjectAccess = accessor => { return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); }; class ExportPropertyMainTemplatePlugin { + /** + * @param {string|string[]} property the name of the property to export + */ constructor(property) { this.property = property; } + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ apply(compilation) { const { mainTemplate, chunkTemplate } = compilation; diff --git a/lib/LibraryTemplatePlugin.js b/lib/LibraryTemplatePlugin.js index 88c342cffe8..cc7c828e180 100644 --- a/lib/LibraryTemplatePlugin.js +++ b/lib/LibraryTemplatePlugin.js @@ -6,30 +6,45 @@ const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin"); +/** @typedef {import("./Compiler")} Compiler */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ const accessorToObjectAccess = accessor => { - return accessor - .map(a => { - return `[${JSON.stringify(a)}]`; - }) - .join(""); + return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); }; -const accessorAccess = (base, accessor, joinWith) => { - accessor = [].concat(accessor); - return accessor - .map((a, idx) => { - a = base - ? base + accessorToObjectAccess(accessor.slice(0, idx + 1)) - : accessor[0] + accessorToObjectAccess(accessor.slice(1, idx + 1)); - if (idx === accessor.length - 1) return a; +/** + * @param {string=} base the path prefix + * @param {string|string[]} accessor the accessor + * @param {string=} joinWith the element separator + * @returns {string} the path + */ +const accessorAccess = (base, accessor, joinWith = "; ") => { + const accessors = Array.isArray(accessor) ? accessor : [accessor]; + return accessors + .map((_, idx) => { + const a = base + ? base + accessorToObjectAccess(accessors.slice(0, idx + 1)) + : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1)); + if (idx === accessors.length - 1) return a; if (idx === 0 && typeof base === "undefined") return `${a} = typeof ${a} === "object" ? ${a} : {}`; return `${a} = ${a} || {}`; }) - .join(joinWith || "; "); + .join(joinWith); }; class LibraryTemplatePlugin { + /** + * @param {string} name name of library + * @param {string} target type of library + * @param {boolean} umdNamedDefine setting this to true will name the UMD module + * @param {string|TODO} auxiliaryComment comment in the UMD wrapper + * @param {string|string[]} exportProperty which export should be exposed as library + */ constructor(name, target, umdNamedDefine, auxiliaryComment, exportProperty) { this.name = name; this.target = target; @@ -38,10 +53,14 @@ class LibraryTemplatePlugin { this.exportProperty = exportProperty; } + /** + * @param {Compiler} compiler the compiler instance + * @returns {void} + */ apply(compiler) { compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", compilation => { if (this.exportProperty) { - var ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin"); + const ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin"); new ExportPropertyMainTemplatePlugin(this.exportProperty).apply( compilation ); @@ -49,66 +68,80 @@ class LibraryTemplatePlugin { switch (this.target) { case "var": new SetVarMainTemplatePlugin( - `var ${accessorAccess(false, this.name)}` + `var ${accessorAccess(undefined, this.name)}`, + false ).apply(compilation); break; case "assign": new SetVarMainTemplatePlugin( - accessorAccess(undefined, this.name) + accessorAccess(undefined, this.name), + false ).apply(compilation); break; case "this": case "self": case "window": - if (this.name) + if (this.name) { new SetVarMainTemplatePlugin( - accessorAccess(this.target, this.name) + accessorAccess(this.target, this.name), + false ).apply(compilation); - else + } else { new SetVarMainTemplatePlugin(this.target, true).apply(compilation); + } break; case "global": - if (this.name) + if (this.name) { new SetVarMainTemplatePlugin( accessorAccess( compilation.runtimeTemplate.outputOptions.globalObject, this.name - ) + ), + false ).apply(compilation); - else + } else { new SetVarMainTemplatePlugin( compilation.runtimeTemplate.outputOptions.globalObject, true ).apply(compilation); + } break; case "commonjs": - if (this.name) + if (this.name) { new SetVarMainTemplatePlugin( - accessorAccess("exports", this.name) + accessorAccess("exports", this.name), + false ).apply(compilation); - else new SetVarMainTemplatePlugin("exports", true).apply(compilation); + } else { + new SetVarMainTemplatePlugin("exports", true).apply(compilation); + } break; case "commonjs2": case "commonjs-module": - new SetVarMainTemplatePlugin("module.exports").apply(compilation); + new SetVarMainTemplatePlugin("module.exports", false).apply( + compilation + ); break; - case "amd": - var AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin"); + case "amd": { + const AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin"); new AmdMainTemplatePlugin(this.name).apply(compilation); break; + } case "umd": - case "umd2": - var UmdMainTemplatePlugin = require("./UmdMainTemplatePlugin"); + case "umd2": { + const UmdMainTemplatePlugin = require("./UmdMainTemplatePlugin"); new UmdMainTemplatePlugin(this.name, { optionalAmdExternalAsGlobal: this.target === "umd2", namedDefine: this.umdNamedDefine, auxiliaryComment: this.auxiliaryComment }).apply(compilation); break; - case "jsonp": - var JsonpExportMainTemplatePlugin = require("./web/JsonpExportMainTemplatePlugin"); + } + case "jsonp": { + const JsonpExportMainTemplatePlugin = require("./web/JsonpExportMainTemplatePlugin"); new JsonpExportMainTemplatePlugin(this.name).apply(compilation); break; + } default: throw new Error(`${this.target} is not a valid Library target`); } diff --git a/lib/SetVarMainTemplatePlugin.js b/lib/SetVarMainTemplatePlugin.js index 441a585d2c5..63db2821a54 100644 --- a/lib/SetVarMainTemplatePlugin.js +++ b/lib/SetVarMainTemplatePlugin.js @@ -6,12 +6,24 @@ const { ConcatSource } = require("webpack-sources"); +/** @typedef {import("./Compilation")} Compilation */ + class SetVarMainTemplatePlugin { + /** + * @param {string} varExpression the accessor where the library is exported + * @param {boolean} copyObject specify copying the exports + */ constructor(varExpression, copyObject) { + /** @type {string} */ this.varExpression = varExpression; + /** @type {boolean} */ this.copyObject = copyObject; } + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ apply(compilation) { const { mainTemplate, chunkTemplate } = compilation; diff --git a/lib/UmdMainTemplatePlugin.js b/lib/UmdMainTemplatePlugin.js index 8f1ea5799c4..5c794767f0a 100644 --- a/lib/UmdMainTemplatePlugin.js +++ b/lib/UmdMainTemplatePlugin.js @@ -7,22 +7,59 @@ const { ConcatSource, OriginalSource } = require("webpack-sources"); const Template = require("./Template"); -function accessorToObjectAccess(accessor) { +/** @typedef {import("./Compilation")} Compilation */ + +/** + * @param {string[]} accessor the accessor to convert to path + * @returns {string} the path + */ +const accessorToObjectAccess = accessor => { return accessor.map(a => `[${JSON.stringify(a)}]`).join(""); -} +}; -function accessorAccess(base, accessor) { - accessor = [].concat(accessor); - return accessor - .map((a, idx) => { - a = base + accessorToObjectAccess(accessor.slice(0, idx + 1)); - if (idx === accessor.length - 1) return a; +/** + * @param {string=} base the path prefix + * @param {string|string[]} accessor the accessor + * @param {string=} joinWith the element separator + * @returns {string} the path + */ +const accessorAccess = (base, accessor, joinWith = ", ") => { + const accessors = Array.isArray(accessor) ? accessor : [accessor]; + return accessors + .map((_, idx) => { + const a = base + ? base + accessorToObjectAccess(accessors.slice(0, idx + 1)) + : accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1)); + if (idx === accessors.length - 1) return a; + if (idx === 0 && typeof base === "undefined") + return `${a} = typeof ${a} === "object" ? ${a} : {}`; return `${a} = ${a} || {}`; }) - .join(", "); -} + .join(joinWith); +}; + +/** @typedef {string | string[] | Record} UmdMainTemplatePluginName */ + +/** + * @typedef {Object} AuxiliaryCommentObject + * @property {string} root + * @property {string} commonjs + * @property {string} commonjs2 + * @property {string} amd + */ + +/** + * @typedef {Object} UmdMainTemplatePluginOption + * @property {boolean=} optionalAmdExternalAsGlobal + * @property {boolean} namedDefine + * @property {string | AuxiliaryCommentObject} auxiliaryComment + */ class UmdMainTemplatePlugin { + /** + * @param {UmdMainTemplatePluginName} name the name of the UMD library + * @param {UmdMainTemplatePluginOption} options the plugin option + */ constructor(name, options) { if (typeof name === "object" && !Array.isArray(name)) { this.name = name.root || name.amd || name.commonjs; @@ -40,6 +77,10 @@ class UmdMainTemplatePlugin { this.auxiliaryComment = options.auxiliaryComment; } + /** + * @param {Compilation} compilation the compilation instance + * @returns {void} + */ apply(compilation) { const { mainTemplate, chunkTemplate, runtimeTemplate } = compilation; @@ -152,23 +193,27 @@ class UmdMainTemplatePlugin { amdFactory = "factory"; } + const auxiliaryComment = this.auxiliaryComment; + + const getAuxilaryComment = type => { + if (auxiliaryComment) { + if (typeof auxiliaryComment === "string") + return "\t//" + auxiliaryComment + "\n"; + if (auxiliaryComment[type]) + return "\t//" + auxiliaryComment[type] + "\n"; + } + return ""; + }; + return new ConcatSource( new OriginalSource( "(function webpackUniversalModuleDefinition(root, factory) {\n" + - (this.auxiliaryComment && typeof this.auxiliaryComment === "string" - ? " //" + this.auxiliaryComment + "\n" - : this.auxiliaryComment.commonjs2 - ? " //" + this.auxiliaryComment.commonjs2 + "\n" - : "") + + getAuxilaryComment("commonjs2") + " if(typeof exports === 'object' && typeof module === 'object')\n" + " module.exports = factory(" + externalsRequireArray("commonjs2") + ");\n" + - (this.auxiliaryComment && typeof this.auxiliaryComment === "string" - ? " //" + this.auxiliaryComment + "\n" - : this.auxiliaryComment.amd - ? " //" + this.auxiliaryComment.amd + "\n" - : "") + + getAuxilaryComment("amd") + " else if(typeof define === 'function' && define.amd)\n" + (requiredExternals.length > 0 ? this.names.amd && this.namedDefine === true @@ -192,24 +237,14 @@ class UmdMainTemplatePlugin { ");\n" : " define([], " + amdFactory + ");\n") + (this.names.root || this.names.commonjs - ? (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" - ? " //" + this.auxiliaryComment + "\n" - : this.auxiliaryComment.commonjs - ? " //" + this.auxiliaryComment.commonjs + "\n" - : "") + + ? getAuxilaryComment("commonjs") + " else if(typeof exports === 'object')\n" + " exports[" + libraryName(this.names.commonjs || this.names.root) + "] = factory(" + externalsRequireArray("commonjs") + ");\n" + - (this.auxiliaryComment && - typeof this.auxiliaryComment === "string" - ? " //" + this.auxiliaryComment + "\n" - : this.auxiliaryComment.root - ? " //" + this.auxiliaryComment.root + "\n" - : "") + + getAuxilaryComment("root") + " else\n" + " " + replaceKeys(