| 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 } = 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").LibraryOptions} LibraryOptions */
|
|---|
| 15 | /** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
|
|---|
| 16 | /** @typedef {import("../Chunk")} Chunk */
|
|---|
| 17 | /** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
|
|---|
| 18 | /** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
|
|---|
| 19 | /** @typedef {import("../util/Hash")} Hash */
|
|---|
| 20 | /**
|
|---|
| 21 | * Defines the shared type used by this module.
|
|---|
| 22 | * @template T
|
|---|
| 23 | * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T>
|
|---|
| 24 | */
|
|---|
| 25 |
|
|---|
| 26 | /**
|
|---|
| 27 | * Defines the amd library plugin options type used by this module.
|
|---|
| 28 | * @typedef {object} AmdLibraryPluginOptions
|
|---|
| 29 | * @property {LibraryType} type
|
|---|
| 30 | * @property {boolean=} requireAsWrapper
|
|---|
| 31 | */
|
|---|
| 32 |
|
|---|
| 33 | /**
|
|---|
| 34 | * Defines the amd library plugin parsed type used by this module.
|
|---|
| 35 | * @typedef {object} AmdLibraryPluginParsed
|
|---|
| 36 | * @property {string} name
|
|---|
| 37 | * @property {string} amdContainer
|
|---|
| 38 | */
|
|---|
| 39 |
|
|---|
| 40 | /**
|
|---|
| 41 | * Represents the amd library plugin runtime component.
|
|---|
| 42 | * @typedef {AmdLibraryPluginParsed} T
|
|---|
| 43 | * @extends {AbstractLibraryPlugin<AmdLibraryPluginParsed>}
|
|---|
| 44 | */
|
|---|
| 45 | class AmdLibraryPlugin extends AbstractLibraryPlugin {
|
|---|
| 46 | /**
|
|---|
| 47 | * Creates an instance of AmdLibraryPlugin.
|
|---|
| 48 | * @param {AmdLibraryPluginOptions} options the plugin options
|
|---|
| 49 | */
|
|---|
| 50 | constructor(options) {
|
|---|
| 51 | super({
|
|---|
| 52 | pluginName: "AmdLibraryPlugin",
|
|---|
| 53 | type: options.type
|
|---|
| 54 | });
|
|---|
| 55 | /** @type {AmdLibraryPluginOptions["requireAsWrapper"]} */
|
|---|
| 56 | this.requireAsWrapper = options.requireAsWrapper;
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | /**
|
|---|
| 60 | * Returns preprocess as needed by overriding.
|
|---|
| 61 | * @param {LibraryOptions} library normalized library option
|
|---|
| 62 | * @returns {T} preprocess as needed by overriding
|
|---|
| 63 | */
|
|---|
| 64 | parseOptions(library) {
|
|---|
| 65 | const { name, amdContainer } = library;
|
|---|
| 66 | if (this.requireAsWrapper) {
|
|---|
| 67 | if (name) {
|
|---|
| 68 | throw new Error(
|
|---|
| 69 | `AMD library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
|
|---|
| 70 | );
|
|---|
| 71 | }
|
|---|
| 72 | } else if (name && typeof name !== "string") {
|
|---|
| 73 | throw new Error(
|
|---|
| 74 | `AMD library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
|
|---|
| 75 | );
|
|---|
| 76 | }
|
|---|
| 77 | const _name = /** @type {string} */ (name);
|
|---|
| 78 | const _amdContainer = /** @type {string} */ (amdContainer);
|
|---|
| 79 | return { name: _name, amdContainer: _amdContainer };
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | /**
|
|---|
| 83 | * Returns source with library export.
|
|---|
| 84 | * @param {Source} source source
|
|---|
| 85 | * @param {RenderContext} renderContext render context
|
|---|
| 86 | * @param {LibraryContext<T>} libraryContext context
|
|---|
| 87 | * @returns {Source} source with library export
|
|---|
| 88 | */
|
|---|
| 89 | render(
|
|---|
| 90 | source,
|
|---|
| 91 | { chunkGraph, chunk, runtimeTemplate },
|
|---|
| 92 | { options, compilation }
|
|---|
| 93 | ) {
|
|---|
| 94 | const modern = runtimeTemplate.supportsArrowFunction();
|
|---|
| 95 | const modules = chunkGraph
|
|---|
| 96 | .getChunkModules(chunk)
|
|---|
| 97 | .filter(
|
|---|
| 98 | (m) =>
|
|---|
| 99 | m instanceof ExternalModule &&
|
|---|
| 100 | (m.externalType === "amd" || m.externalType === "amd-require")
|
|---|
| 101 | );
|
|---|
| 102 | const externals = /** @type {ExternalModule[]} */ (modules);
|
|---|
| 103 | const externalsDepsArray = JSON.stringify(
|
|---|
| 104 | externals.map((m) =>
|
|---|
| 105 | typeof m.request === "object" && !Array.isArray(m.request)
|
|---|
| 106 | ? m.request.amd
|
|---|
| 107 | : m.request
|
|---|
| 108 | )
|
|---|
| 109 | );
|
|---|
| 110 | const externalsArguments = externals
|
|---|
| 111 | .map(
|
|---|
| 112 | (m) =>
|
|---|
| 113 | `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
|
|---|
| 114 | `${chunkGraph.getModuleId(m)}`
|
|---|
| 115 | )}__`
|
|---|
| 116 | )
|
|---|
| 117 | .join(", ");
|
|---|
| 118 |
|
|---|
| 119 | const iife = runtimeTemplate.isIIFE();
|
|---|
| 120 | const fnStart =
|
|---|
| 121 | (modern
|
|---|
| 122 | ? `(${externalsArguments}) => {`
|
|---|
| 123 | : `function(${externalsArguments}) {`) +
|
|---|
| 124 | (iife || !chunk.hasRuntime() ? " return " : "\n");
|
|---|
| 125 | const fnEnd = iife ? ";\n}" : "\n}";
|
|---|
| 126 |
|
|---|
| 127 | let amdContainerPrefix = "";
|
|---|
| 128 | if (options.amdContainer) {
|
|---|
| 129 | amdContainerPrefix = `${options.amdContainer}.`;
|
|---|
| 130 | }
|
|---|
| 131 |
|
|---|
| 132 | if (this.requireAsWrapper) {
|
|---|
| 133 | return new ConcatSource(
|
|---|
| 134 | `${amdContainerPrefix}require(${externalsDepsArray}, ${fnStart}`,
|
|---|
| 135 | source,
|
|---|
| 136 | `${fnEnd});`
|
|---|
| 137 | );
|
|---|
| 138 | } else if (options.name) {
|
|---|
| 139 | const name = compilation.getPath(options.name, {
|
|---|
| 140 | chunk
|
|---|
| 141 | });
|
|---|
| 142 |
|
|---|
| 143 | return new ConcatSource(
|
|---|
| 144 | `${amdContainerPrefix}define(${JSON.stringify(
|
|---|
| 145 | name
|
|---|
| 146 | )}, ${externalsDepsArray}, ${fnStart}`,
|
|---|
| 147 | source,
|
|---|
| 148 | `${fnEnd});`
|
|---|
| 149 | );
|
|---|
| 150 | } else if (externalsArguments) {
|
|---|
| 151 | return new ConcatSource(
|
|---|
| 152 | `${amdContainerPrefix}define(${externalsDepsArray}, ${fnStart}`,
|
|---|
| 153 | source,
|
|---|
| 154 | `${fnEnd});`
|
|---|
| 155 | );
|
|---|
| 156 | }
|
|---|
| 157 | return new ConcatSource(
|
|---|
| 158 | `${amdContainerPrefix}define(${fnStart}`,
|
|---|
| 159 | source,
|
|---|
| 160 | `${fnEnd});`
|
|---|
| 161 | );
|
|---|
| 162 | }
|
|---|
| 163 |
|
|---|
| 164 | /**
|
|---|
| 165 | * Processes the provided chunk.
|
|---|
| 166 | * @param {Chunk} chunk the chunk
|
|---|
| 167 | * @param {Hash} hash hash
|
|---|
| 168 | * @param {ChunkHashContext} chunkHashContext chunk hash context
|
|---|
| 169 | * @param {LibraryContext<T>} libraryContext context
|
|---|
| 170 | * @returns {void}
|
|---|
| 171 | */
|
|---|
| 172 | chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
|
|---|
| 173 | hash.update("AmdLibraryPlugin");
|
|---|
| 174 | if (this.requireAsWrapper) {
|
|---|
| 175 | hash.update("requireAsWrapper");
|
|---|
| 176 | } else if (options.name) {
|
|---|
| 177 | hash.update("named");
|
|---|
| 178 | const name = compilation.getPath(options.name, {
|
|---|
| 179 | chunk
|
|---|
| 180 | });
|
|---|
| 181 | hash.update(name);
|
|---|
| 182 | } else if (options.amdContainer) {
|
|---|
| 183 | hash.update("amdContainer");
|
|---|
| 184 | hash.update(options.amdContainer);
|
|---|
| 185 | }
|
|---|
| 186 | }
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| 189 | module.exports = AmdLibraryPlugin;
|
|---|