webpack
Version:
Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.
187 lines (179 loc) • 5.76 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const SetVarMainTemplatePlugin = require("./SetVarMainTemplatePlugin");
/** @typedef {import("../declarations/WebpackOptions").LibraryCustomUmdObject} LibraryCustomUmdObject */
/** @typedef {import("./Compiler")} Compiler */
/**
* @param {string[]} accessor the accessor to convert to path
* @returns {string} the path
*/
const accessorToObjectAccess = accessor => {
return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
};
/**
* @param {string=} base the path prefix
* @param {string|string[]|LibraryCustomUmdObject} accessor the accessor
* @param {"amd" | "commonjs" | "root"} umdProperty property used when a custom umd object is provided
* @param {string=} joinWith the element separator
* @returns {string} the path
*/
const accessorAccess = (base, accessor, umdProperty, joinWith = "; ") => {
const normalizedAccessor =
typeof accessor === "object" && !Array.isArray(accessor)
? accessor[umdProperty]
: accessor;
const accessors = Array.isArray(normalizedAccessor)
? normalizedAccessor
: [normalizedAccessor];
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 && base === undefined) {
return `${a} = typeof ${a} === "object" ? ${a} : {}`;
}
return `${a} = ${a} || {}`;
})
.join(joinWith);
};
class LibraryTemplatePlugin {
/**
* @param {string|string[]|LibraryCustomUmdObject} 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;
this.umdNamedDefine = umdNamedDefine;
this.auxiliaryComment = auxiliaryComment;
this.exportProperty = exportProperty;
}
/**
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.thisCompilation.tap("LibraryTemplatePlugin", compilation => {
if (this.exportProperty) {
const ExportPropertyMainTemplatePlugin = require("./ExportPropertyMainTemplatePlugin");
new ExportPropertyMainTemplatePlugin(this.exportProperty).apply(
compilation
);
}
switch (this.target) {
case "var":
if (
!this.name ||
(typeof this.name === "object" && !Array.isArray(this.name))
) {
throw new Error(
"library name must be set and not an UMD custom object for non-UMD target"
);
}
new SetVarMainTemplatePlugin(
`var ${accessorAccess(undefined, this.name, "root")}`,
false
).apply(compilation);
break;
case "assign":
new SetVarMainTemplatePlugin(
accessorAccess(undefined, this.name, "root"),
false
).apply(compilation);
break;
case "this":
case "self":
case "window":
if (this.name) {
new SetVarMainTemplatePlugin(
accessorAccess(this.target, this.name, "root"),
false
).apply(compilation);
} else {
new SetVarMainTemplatePlugin(this.target, true).apply(compilation);
}
break;
case "global":
if (this.name) {
new SetVarMainTemplatePlugin(
accessorAccess(
compilation.runtimeTemplate.outputOptions.globalObject,
this.name,
"root"
),
false
).apply(compilation);
} else {
new SetVarMainTemplatePlugin(
compilation.runtimeTemplate.outputOptions.globalObject,
true
).apply(compilation);
}
break;
case "commonjs":
if (this.name) {
new SetVarMainTemplatePlugin(
accessorAccess("exports", this.name, "commonjs"),
false
).apply(compilation);
} else {
new SetVarMainTemplatePlugin("exports", true).apply(compilation);
}
break;
case "commonjs2":
case "commonjs-module":
new SetVarMainTemplatePlugin("module.exports", false).apply(
compilation
);
break;
case "amd":
case "amd-require": {
const AmdMainTemplatePlugin = require("./AmdMainTemplatePlugin");
if (this.name && typeof this.name !== "string") {
throw new Error("library name must be a string for amd target");
}
new AmdMainTemplatePlugin({
name: this.name,
requireAsWrapper: this.target === "amd-require"
}).apply(compilation);
break;
}
case "umd":
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": {
const JsonpExportMainTemplatePlugin = require("./web/JsonpExportMainTemplatePlugin");
if (typeof this.name !== "string")
throw new Error("library name must be a string for jsonp target");
new JsonpExportMainTemplatePlugin(this.name).apply(compilation);
break;
}
case "system": {
const SystemMainTemplatePlugin = require("./SystemMainTemplatePlugin");
new SystemMainTemplatePlugin({
name: this.name
}).apply(compilation);
break;
}
default:
throw new Error(`${this.target} is not a valid Library target`);
}
});
}
}
module.exports = LibraryTemplatePlugin;