| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const { SyncBailHook } = require("tapable");
- const { OriginalSource, RawSource } = require("webpack-sources");
- const ConcatenationScope = require("./ConcatenationScope");
- const { UsageState } = require("./ExportsInfo");
- const InitFragment = require("./InitFragment");
- const Module = require("./Module");
- const {
- ASSET_URL_TYPE,
- ASSET_URL_TYPES,
- CSS_IMPORT_TYPES,
- JAVASCRIPT_TYPE,
- JAVASCRIPT_TYPES
- } = require("./ModuleSourceTypeConstants");
- const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("./ModuleTypeConstants");
- const RuntimeGlobals = require("./RuntimeGlobals");
- const Template = require("./Template");
- const WebpackError = require("./WebpackError");
- const { DEFAULTS } = require("./config/defaults");
- const { ImportPhaseUtils } = require("./dependencies/ImportPhase");
- const StaticExportsDependency = require("./dependencies/StaticExportsDependency");
- const { coreModules } = require("./node/nodeBuiltins");
- const createHash = require("./util/createHash");
- const createHooksRegistry = require("./util/createHooksRegistry");
- const extractUrlAndGlobal = require("./util/extractUrlAndGlobal");
- const makeSerializable = require("./util/makeSerializable");
- const memoize = require("./util/memoize");
- const { propertyAccess } = require("./util/property");
- const { register } = require("./util/serialization");
- const getEnvironmentNotSupportAsyncWarning = memoize(() =>
- require("./errors/EnvironmentNotSupportAsyncWarning")
- );
- /** @import { Source } from "webpack-sources" */
- /**
- * @import {
- * ExternalsType,
- * HashFunction,
- * ExternalItemInterop as ExternalInterop
- * } from "../declarations/WebpackOptions"
- */
- /**
- * @import {
- * WebpackOptionsNormalizedWithDefaults as WebpackOptions
- * } from "./config/defaults"
- */
- /** @import Chunk from "./Chunk" */
- /** @import ChunkGraph, { ModuleId } from "./ChunkGraph" */
- /** @import Compilation, { UnsafeCacheData } from "./Compilation" */
- /** @import { UpdateHashContext } from "./Dependency" */
- /** @import ExportsInfo from "./ExportsInfo" */
- /** @import { GenerateContext } from "./Generator" */
- /**
- * @import {
- * BuildMeta,
- * BuildCallback,
- * BuildInfo,
- * CodeGenerationContext,
- * CodeGenerationResult,
- * CodeGenerationResultData,
- * ConcatenationBailoutReasonContext,
- * LibIdentOptions,
- * LibIdent,
- * NeedBuildCallback,
- * NeedBuildContext,
- * RuntimeRequirements,
- * ReadOnlyRuntimeRequirements,
- * Sources,
- * SourceTypes
- * } from "./Module"
- */
- /** @import ModuleGraph from "./ModuleGraph" */
- /** @import { ConnectionState } from "./ModuleGraphConnection" */
- /** @import NormalModuleFactory from "./NormalModuleFactory" */
- /** @import RequestShortener from "./RequestShortener" */
- /** @import { ResolverWithOptions } from "./ResolverFactory" */
- /** @import RuntimeTemplate from "./RuntimeTemplate" */
- /**
- * @import {
- * ChunkRenderContext
- * } from "./javascript/JavascriptModulesPlugin"
- */
- /** @import { ImportAttributes } from "./javascript/JavascriptParser" */
- /** @import { ImportPhaseType } from "./dependencies/ImportPhase" */
- /** @typedef {import("./serialization/ObjectMiddleware").ObjectDeserializerContext<[ExternalModuleRequest, ExternalsType, string, DependencyMeta | undefined, ExternalInterop | undefined, boolean | undefined]>} ObjectDeserializerContext */
- /** @typedef {import("./serialization/ObjectMiddleware").ObjectSerializerContext<[ExternalModuleRequest, ExternalsType, string, DependencyMeta | undefined, ExternalInterop | undefined, boolean | undefined]>} ObjectSerializerContext */
- /** @import Hash from "./util/Hash" */
- /** @import { InputFileSystem } from "./util/fs" */
- /** @import { RuntimeSpec } from "./util/runtime" */
- /** @typedef {{ attributes?: ImportAttributes, phase?: ImportPhaseType, externalType: "import" | "module" | undefined }} ImportDependencyMeta */
- /** @typedef {{ layer?: string, supports?: string, media?: string }} CssImportDependencyMeta */
- /** @typedef {{ sourceType: "asset-url" | "css-url" }} AssetDependencyMeta */
- /** @typedef {ImportDependencyMeta | CssImportDependencyMeta | AssetDependencyMeta} DependencyMeta */
- /**
- * Defines the source data type used by this module.
- * @typedef {object} SourceData
- * @property {boolean=} iife
- * @property {string=} init
- * @property {string} expression
- * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
- * @property {ReadOnlyRuntimeRequirements=} runtimeRequirements
- * @property {[string, string][]=} specifiers
- */
- /** @typedef {true | [string, string][]} Imported */
- /** @type {RuntimeRequirements} */
- const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
- /** @type {RuntimeRequirements} */
- const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]);
- /** @type {RuntimeRequirements} */
- const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([
- RuntimeGlobals.definePropertyGetters
- ]);
- /** @type {RuntimeRequirements} */
- const EMPTY_RUNTIME_REQUIREMENTS = new Set();
- const NODE_PREFIX = "node:";
- // externals of these types are wired by the library wrapper, which does its own per-key lookup on object externals
- const LIBRARY_WIRED_EXTERNAL_TYPES = new Set([
- "amd",
- "amd-require",
- "umd",
- "umd2",
- "system",
- "jsonp"
- ]);
- // External types that emit a node.js-resolvable specifier (`require`/`import`).
- const NODE_RESOLVING_EXTERNAL_TYPES = new Set([
- "commonjs",
- "commonjs2",
- "commonjs-module",
- "commonjs-static",
- "node-commonjs",
- "import",
- "module"
- ]);
- /**
- * Normalizes a node.js core module specifier for the target. Strips `node:`
- * when the target can't resolve a prefixed request, adds `node:` for a universal
- * bundle (which may run on deno/bun where the prefix is required), and otherwise
- * keeps the author's original notation.
- * @param {string | string[]} request the external request
- * @param {ExternalsType} externalType the resolved external type
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {string | string[]} the normalized request
- */
- const normalizeNodeCoreModuleRequest = (
- request,
- externalType,
- runtimeTemplate
- ) => {
- if (!NODE_RESOLVING_EXTERNAL_TYPES.has(externalType)) return request;
- const name = Array.isArray(request) ? request[0] : request;
- if (typeof name !== "string") return request;
- /**
- * @param {string} next replacement specifier
- * @returns {string | string[]} request with the specifier swapped
- */
- const withName = (next) =>
- Array.isArray(request) ? [next, ...request.slice(1)] : next;
- if (
- runtimeTemplate.outputOptions.environment.nodePrefixForCoreModules === false
- ) {
- if (!name.startsWith(NODE_PREFIX)) return request;
- const stripped = name.slice(NODE_PREFIX.length);
- return coreModules.has(stripped) ? withName(stripped) : request;
- }
- if (runtimeTemplate.isUniversalTarget() && !name.startsWith(NODE_PREFIX)) {
- return coreModules.has(name) ? withName(NODE_PREFIX + name) : request;
- }
- return request;
- };
- /**
- * Gets source for global variable external.
- * @param {string | string[]} variableName the variable name or path
- * @param {string} type the module system
- * @returns {SourceData} the generated source
- */
- const getSourceForGlobalVariableExternal = (variableName, type) => {
- if (!Array.isArray(variableName)) {
- // make it an array as the look up works the same basically
- variableName = [variableName];
- }
- // needed for e.g. window["some"]["thing"]
- const objectLookup = variableName
- .map((r) => `[${JSON.stringify(r)}]`)
- .join("");
- return {
- iife: type === "this",
- expression: `${type}${objectLookup}`
- };
- };
- /** @typedef {string | string[]} ModuleAndSpecifiers */
- /**
- * Gets source for common js external.
- * @param {ModuleAndSpecifiers} moduleAndSpecifiers the module request
- * @returns {SourceData} the generated source
- */
- const getSourceForCommonJsExternal = (moduleAndSpecifiers) => {
- if (!Array.isArray(moduleAndSpecifiers)) {
- return {
- expression: `require(${JSON.stringify(moduleAndSpecifiers)})`
- };
- }
- const moduleName = moduleAndSpecifiers[0];
- return {
- expression: `require(${JSON.stringify(moduleName)})${propertyAccess(
- moduleAndSpecifiers,
- 1
- )}`
- };
- };
- /**
- * Gets external module node commonjs init fragment.
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {boolean=} universal target may also run outside node (e.g. `["node", "web"]`)
- * @returns {InitFragment<ChunkRenderContext>} code
- */
- const getExternalModuleNodeCommonjsInitFragment = (
- runtimeTemplate,
- universal = false
- ) => {
- const importMetaName = runtimeTemplate.outputOptions.importMetaName;
- const moduleId = runtimeTemplate.renderNodePrefixForCoreModule("module");
- if (!universal) {
- return new InitFragment(
- `import { createRequire as __WEBPACK_EXTERNAL_createRequire } from ${moduleId};\n${runtimeTemplate.renderConst()} __WEBPACK_EXTERNAL_createRequire_require = __WEBPACK_EXTERNAL_createRequire(${importMetaName}.url);\n`,
- InitFragment.STAGE_HARMONY_IMPORTS,
- 0,
- "external module node-commonjs"
- );
- }
- // defensively obtain `createRequire` so the universal bundle still loads off node
- const content = `${runtimeTemplate.renderConst()} __WEBPACK_EXTERNAL_createRequire_require = ${runtimeTemplate.getBuiltinModule(
- moduleId,
- `.createRequire(${importMetaName}.url)`
- )};\n`;
- return new InitFragment(
- content,
- InitFragment.STAGE_HARMONY_IMPORTS,
- 0,
- "external module node-commonjs universal"
- );
- };
- /**
- * Gets source for common js external in node module.
- * @param {ModuleAndSpecifiers} moduleAndSpecifiers the module request
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {boolean=} universal target may also run outside node (e.g. `["node", "web"]`)
- * @returns {SourceData} the generated source
- */
- const getSourceForCommonJsExternalInNodeModule = (
- moduleAndSpecifiers,
- runtimeTemplate,
- universal = false
- ) => {
- const chunkInitFragments = [
- getExternalModuleNodeCommonjsInitFragment(runtimeTemplate, universal)
- ];
- if (!Array.isArray(moduleAndSpecifiers)) {
- return {
- chunkInitFragments,
- expression: `__WEBPACK_EXTERNAL_createRequire_require(${JSON.stringify(
- moduleAndSpecifiers
- )})`
- };
- }
- const moduleName = moduleAndSpecifiers[0];
- return {
- chunkInitFragments,
- expression: `__WEBPACK_EXTERNAL_createRequire_require(${JSON.stringify(
- moduleName
- )})${propertyAccess(moduleAndSpecifiers, 1)}`
- };
- };
- /**
- * A phase is syntax the target has to read, with no form to fall back to. Reported
- * like the `import()` check beside it, so the build fails rather than the bundle.
- * @param {ImportPhaseType | undefined} phase the phase the reference asks for
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {void}
- */
- const checkPhaseIsSupported = (phase, runtimeTemplate) => {
- if (
- ImportPhaseUtils.isDefer(phase) &&
- !runtimeTemplate.supportsDeferImport()
- ) {
- throw new Error(
- "The target environment doesn't support 'import defer', so an external cannot be imported in the defer phase. Set 'output.environment.deferImport' when the target reads it."
- );
- }
- if (
- ImportPhaseUtils.isSource(phase) &&
- !runtimeTemplate.supportsSourceImport()
- ) {
- throw new Error(
- "The target environment doesn't support 'import source', so an external cannot be imported in the source phase. Set 'output.environment.sourceImport' when the target reads it."
- );
- }
- };
- /**
- * Gets source for import external.
- * @param {ModuleAndSpecifiers} moduleAndSpecifiers the module request
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {ImportDependencyMeta=} dependencyMeta the dependency meta
- * @returns {SourceData} the generated source
- */
- const getSourceForImportExternal = (
- moduleAndSpecifiers,
- runtimeTemplate,
- dependencyMeta
- ) => {
- const baseImportName = runtimeTemplate.outputOptions.importFunctionName;
- if (
- !runtimeTemplate.supportsDynamicImport() &&
- (baseImportName === "import" || baseImportName === "module-import")
- ) {
- throw new Error(
- "The target environment doesn't support 'import()' so it's not possible to use external type 'import'"
- );
- }
- const phase = dependencyMeta && dependencyMeta.phase;
- checkPhaseIsSupported(phase, runtimeTemplate);
- // `import.defer(…)` and `import.source(…)` are only valid forms of the
- // native `import(…)` function, so we only emit the phase suffix when the
- // importFunctionName is the default `"import"`. Anything else has no phase
- // form at all, and dropping it would silently import eagerly instead.
- if (
- baseImportName !== "import" &&
- (ImportPhaseUtils.isDefer(phase) || ImportPhaseUtils.isSource(phase))
- ) {
- throw new Error(
- `'import.defer' and 'import.source' are forms of the native 'import()', so an external cannot be imported in a phase while 'output.importFunctionName' is '${baseImportName}'`
- );
- }
- const importName = ImportPhaseUtils.isDefer(phase)
- ? "import.defer"
- : ImportPhaseUtils.isSource(phase)
- ? "import.source"
- : baseImportName;
- const attributes =
- dependencyMeta && dependencyMeta.attributes
- ? dependencyMeta.attributes._isLegacyAssert
- ? `, { assert: ${JSON.stringify(
- dependencyMeta.attributes,
- importAssertionReplacer
- )} }`
- : `, { with: ${JSON.stringify(dependencyMeta.attributes)} }`
- : "";
- // `import.source(…)` resolves to the source object itself, while every other
- // external here resolves to a namespace. Consumers unwrap `default` to reach a
- // source, so hand them that shape rather than a value they read `default` off.
- const asNamespace = ImportPhaseUtils.isSource(phase)
- ? `.then(${runtimeTemplate.returningFunction('{ "default": m }', "m")})`
- : "";
- if (!Array.isArray(moduleAndSpecifiers)) {
- return {
- expression: `${importName}(${JSON.stringify(
- moduleAndSpecifiers
- )}${attributes})${asNamespace};`
- };
- }
- if (moduleAndSpecifiers.length === 1) {
- return {
- expression: `${importName}(${JSON.stringify(
- moduleAndSpecifiers[0]
- )}${attributes})${asNamespace};`
- };
- }
- const moduleName = moduleAndSpecifiers[0];
- return {
- expression: `${importName}(${JSON.stringify(
- moduleName
- )}${attributes}).then(${runtimeTemplate.returningFunction(
- `module${propertyAccess(moduleAndSpecifiers, 1)}`,
- "module"
- )});`
- };
- };
- /**
- * Import assertion replacer.
- * @param {string} key key
- * @param {ImportAttributes | string | boolean | undefined} value value
- * @returns {ImportAttributes | string | boolean | undefined} replaced value
- */
- const importAssertionReplacer = (key, value) => {
- if (key === "_isLegacyAssert") {
- return;
- }
- return value;
- };
- /**
- * Represents ModuleExternalInitFragment.
- * @extends {InitFragment<GenerateContext>}
- */
- class ModuleExternalInitFragment extends InitFragment {
- /**
- * Creates an instance of ModuleExternalInitFragment.
- * @param {string} request import source
- * @param {Imported} imported the imported specifiers
- * @param {string=} ident recomputed ident
- * @param {ImportDependencyMeta=} dependencyMeta the dependency meta
- * @param {HashFunction=} hashFunction the hash function to use
- */
- constructor(
- request,
- imported,
- ident,
- dependencyMeta,
- hashFunction = DEFAULTS.HASH_FUNCTION
- ) {
- if (ident === undefined) {
- ident = Template.toIdentifier(request);
- if (ident !== request) {
- ident += `_${createHash(hashFunction)
- .update(request)
- .digest("hex")
- .slice(0, 8)}`;
- }
- // One request in two phases is two imports, so the phase must reach the dedupe
- // key and the binding name — otherwise one silently replaces the other.
- const phase = dependencyMeta && dependencyMeta.phase;
- if (ImportPhaseUtils.isDefer(phase)) {
- ident += "_defer";
- } else if (ImportPhaseUtils.isSource(phase)) {
- ident += "_source";
- }
- }
- super(
- "",
- InitFragment.STAGE_HARMONY_IMPORTS,
- 0,
- `external module import ${ident} ${
- imported === true ? imported : imported.join(" ")
- }`
- );
- /** @type {string} */
- this._ident = ident;
- /** @type {string} */
- this._request = request;
- /** @type {ImportDependencyMeta | undefined} */
- this._dependencyMeta = dependencyMeta;
- /** @type {string} */
- this._identifier = this.buildIdentifier(ident);
- /** @type {Imported} */
- this._imported = this.buildImported(imported);
- }
- /**
- * Returns imported.
- * @returns {Imported} imported
- */
- getImported() {
- return this._imported;
- }
- /**
- * Updates imported using the provided imported.
- * @param {Imported} imported imported
- */
- setImported(imported) {
- this._imported = imported;
- }
- /**
- * Returns the source code that will be included as initialization code.
- * @param {GenerateContext} context context
- * @returns {string | Source | undefined} the source code that will be included as initialization code
- */
- getContent(context) {
- const {
- _dependencyMeta: dependencyMeta,
- _imported: imported,
- _request: request,
- _identifier: identifier
- } = this;
- const attributes =
- dependencyMeta && dependencyMeta.attributes
- ? dependencyMeta.attributes._isLegacyAssert
- ? ` assert ${JSON.stringify(
- dependencyMeta.attributes,
- importAssertionReplacer
- )}`
- : ` with ${JSON.stringify(dependencyMeta.attributes)}`
- : "";
- const phase = dependencyMeta && dependencyMeta.phase;
- checkPhaseIsSupported(phase, context.runtimeTemplate);
- let content = "";
- if (ImportPhaseUtils.isSource(phase) && imported === true) {
- // There is no `import source * as ns` form: the source phase binds one
- // identifier, so it stands in for the namespace the other branches build.
- content = `import source ${identifier} from ${JSON.stringify(
- request
- )}${attributes};\n`;
- } else if (imported === true) {
- // namespace
- const phaseKeyword = ImportPhaseUtils.isDefer(phase) ? "defer " : "";
- content = `import ${phaseKeyword}* as ${identifier} from ${JSON.stringify(
- request
- )}${attributes};\n`;
- } else if (imported.length === 0) {
- // just import, no use
- content = `import ${JSON.stringify(request)}${attributes};\n`;
- } else if (
- ImportPhaseUtils.isSource(phase) &&
- imported.length === 1 &&
- imported[0][0] === "default"
- ) {
- // `import source x from "…"` — the source-phase form binds the source
- // object directly to a single identifier (no namespace, no destructuring).
- content = `import source ${imported[0][1]} from ${JSON.stringify(
- request
- )}${attributes};\n`;
- } else {
- content = `import { ${imported
- .map(([name, finalName]) => {
- if (name !== finalName) {
- return `${name} as ${finalName}`;
- }
- return name;
- })
- .join(", ")} } from ${JSON.stringify(request)}${attributes};\n`;
- }
- return content;
- }
- getNamespaceIdentifier() {
- return this._identifier;
- }
- /**
- * Returns identifier.
- * @param {string} ident ident
- * @returns {string} identifier
- */
- buildIdentifier(ident) {
- return `__WEBPACK_EXTERNAL_MODULE_${ident}__`;
- }
- /**
- * Returns normalized imported.
- * @param {Imported} imported imported
- * @returns {Imported} normalized imported
- */
- buildImported(imported) {
- if (Array.isArray(imported)) {
- return imported.map(([name]) => {
- const ident = `${this._ident}_${name}`;
- return [name, this.buildIdentifier(ident)];
- });
- }
- return imported;
- }
- }
- register(
- ModuleExternalInitFragment,
- "webpack/lib/ExternalModule",
- "ModuleExternalInitFragment",
- {
- serialize(obj, { write }) {
- write(obj._request);
- write(obj._imported);
- write(obj._ident);
- write(obj._dependencyMeta);
- },
- deserialize({ read }) {
- return new ModuleExternalInitFragment(read(), read(), read(), read());
- }
- }
- );
- /**
- * Generates module remapping.
- * @param {string} input input
- * @param {ExportsInfo} exportsInfo the exports info
- * @param {RuntimeSpec=} runtime the runtime
- * @param {RuntimeTemplate=} runtimeTemplate the runtime template
- * @returns {string | undefined} the module remapping
- */
- const generateModuleRemapping = (
- input,
- exportsInfo,
- runtime,
- runtimeTemplate
- ) => {
- if (exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused) {
- /** @type {string[]} */
- const properties = [];
- for (const exportInfo of exportsInfo.orderedExports) {
- const used = exportInfo.getUsedName(exportInfo.name, runtime);
- if (!used) continue;
- const nestedInfo = exportInfo.getNestedExportsInfo();
- if (nestedInfo) {
- const nestedExpr = generateModuleRemapping(
- `${input}${propertyAccess([exportInfo.name])}`,
- nestedInfo
- );
- if (nestedExpr) {
- properties.push(`[${JSON.stringify(used)}]: y(${nestedExpr})`);
- continue;
- }
- }
- properties.push(
- `[${JSON.stringify(used)}]: ${
- /** @type {RuntimeTemplate} */ (runtimeTemplate).returningFunction(
- `${input}${propertyAccess([exportInfo.name])}`
- )
- }`
- );
- }
- return `x({ ${properties.join(", ")} })`;
- }
- };
- /**
- * Gets source for module external.
- * @param {ModuleAndSpecifiers} moduleAndSpecifiers the module request
- * @param {ExportsInfo} exportsInfo exports info of this module
- * @param {RuntimeSpec} runtime the runtime
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {ImportDependencyMeta} dependencyMeta the dependency meta
- * @param {ConcatenationScope=} concatenationScope concatenationScope
- * @returns {SourceData} the generated source
- */
- const getSourceForModuleExternal = (
- moduleAndSpecifiers,
- exportsInfo,
- runtime,
- runtimeTemplate,
- dependencyMeta,
- concatenationScope
- ) => {
- const phase = dependencyMeta && dependencyMeta.phase;
- /** @type {Imported} */
- let imported = true;
- if (concatenationScope) {
- const usedExports = exportsInfo.getUsedExports(runtime);
- switch (usedExports) {
- case true:
- case null:
- // unknown exports
- imported = true;
- break;
- case false:
- // no used exports
- imported = [];
- break;
- default:
- imported = [...usedExports.entries()];
- }
- }
- if (!Array.isArray(moduleAndSpecifiers)) {
- moduleAndSpecifiers = [moduleAndSpecifiers];
- }
- // Return to `namespace` when the external request includes a specific export
- if (moduleAndSpecifiers.length > 1) {
- imported = true;
- }
- // `import defer …` is only valid as `import defer * as ns from "…"`, so
- // keep the namespace form even if usage analysis would otherwise narrow
- // the import down to specific names. Defer + concatenation is semantically
- // at odds (lazy vs. eager), so we preserve the user-written shape here.
- if (ImportPhaseUtils.isDefer(phase)) {
- imported = true;
- }
- // A source phase binds `default` alone. With nothing used the list would be empty
- // and emit `import "…"`, evaluating the module whose source was asked for instead.
- if (
- ImportPhaseUtils.isSource(phase) &&
- Array.isArray(imported) &&
- imported.length === 0
- ) {
- imported = [["default", "default"]];
- }
- const initFragment = new ModuleExternalInitFragment(
- moduleAndSpecifiers[0],
- imported,
- undefined,
- dependencyMeta,
- runtimeTemplate.outputOptions.hashFunction
- );
- const normalizedImported = initFragment.getImported();
- const baseAccess = `${initFragment.getNamespaceIdentifier()}${propertyAccess(
- moduleAndSpecifiers,
- 1
- )}`;
- let expression = baseAccess;
- // A source-phase binding is not a namespace object, so nothing about it can be
- // remapped export by export — the binding itself is what the reference reads.
- const useNamespace = imported === true && !ImportPhaseUtils.isSource(phase);
- /** @type {undefined | string} */
- let moduleRemapping;
- if (useNamespace) {
- moduleRemapping = generateModuleRemapping(
- baseAccess,
- exportsInfo,
- runtime,
- runtimeTemplate
- );
- expression = moduleRemapping || baseAccess;
- }
- return {
- expression,
- init: moduleRemapping
- ? `${runtimeTemplate.renderConst()} x = ${runtimeTemplate.basicFunction(
- "y",
- `${runtimeTemplate.renderConst()} x = {}; ${
- RuntimeGlobals.definePropertyGetters
- }(x, y); return x`
- )} \n${runtimeTemplate.renderConst()} y = ${runtimeTemplate.returningFunction(
- runtimeTemplate.returningFunction("x"),
- "x"
- )}`
- : undefined,
- specifiers: normalizedImported === true ? undefined : normalizedImported,
- runtimeRequirements: moduleRemapping
- ? RUNTIME_REQUIREMENTS_FOR_MODULE
- : undefined,
- chunkInitFragments: [
- /** @type {InitFragment<EXPECTED_ANY>} */ (initFragment)
- ]
- };
- };
- /**
- * Gets source for script external.
- * @param {string | string[]} urlAndGlobal the script request
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {SourceData} the generated source
- */
- const getSourceForScriptExternal = (urlAndGlobal, runtimeTemplate) => {
- if (typeof urlAndGlobal === "string") {
- urlAndGlobal = extractUrlAndGlobal(urlAndGlobal);
- }
- const url = urlAndGlobal[0];
- const globalName = urlAndGlobal[1];
- return {
- init: `${runtimeTemplate.renderConst()} __webpack_error__ = new Error();`,
- expression: `new Promise(${runtimeTemplate.basicFunction(
- "resolve, reject",
- [
- `if(typeof ${globalName} !== "undefined") return resolve();`,
- `${RuntimeGlobals.loadScript}(${JSON.stringify(
- url
- )}, ${runtimeTemplate.basicFunction("event", [
- `if(typeof ${globalName} !== "undefined") return resolve();`,
- `${runtimeTemplate.renderConst()} errorType = event && (event.type === 'load' ? 'missing' : event.type);`,
- `${runtimeTemplate.renderConst()} realSrc = event && event.target && event.target.src;`,
- "__webpack_error__.message = 'Loading script failed.\\n(' + errorType + ': ' + realSrc + ')';",
- "__webpack_error__.name = 'ScriptExternalLoadError';",
- "__webpack_error__.type = errorType;",
- "__webpack_error__.request = realSrc;",
- "__webpack_error__.event = event;",
- "reject(__webpack_error__);"
- ])}, ${JSON.stringify(globalName)});`
- ]
- )}).then(${runtimeTemplate.returningFunction(
- `${globalName}${propertyAccess(urlAndGlobal, 2)}`
- )})`,
- runtimeRequirements: RUNTIME_REQUIREMENTS_FOR_SCRIPT
- };
- };
- /**
- * Gets source for amd-async external. Loads the module at runtime via the
- * asynchronous AMD `require([...])` API and exposes it as an async module,
- * so no AMD library wrapper around the chunk is needed.
- * @param {string | string[]} request the request path
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {SourceData} the generated source
- */
- const getSourceForAmdAsyncExternal = (request, runtimeTemplate) => {
- if (!Array.isArray(request)) {
- request = [request];
- }
- const { library } = runtimeTemplate.outputOptions;
- const amdRequire =
- library && library.amdContainer
- ? `${library.amdContainer}.require`
- : "require";
- return {
- expression: `new Promise(${runtimeTemplate.basicFunction(
- "resolve, reject",
- [
- `if (typeof ${amdRequire} !== "function") return reject(new Error(${JSON.stringify(
- `AMD 'require' is not available to load external module ${request[0]}`
- )}));`,
- `${amdRequire}(${JSON.stringify([
- request[0]
- ])}, ${runtimeTemplate.basicFunction(
- "module",
- `resolve(module${propertyAccess(request, 1)});`
- )}, reject);`
- ]
- )})`
- };
- };
- /**
- * Checks external variable.
- * @param {string} variableName the variable name to check
- * @param {string} request the request path
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {string} the generated source
- */
- const checkExternalVariable = (variableName, request, runtimeTemplate) =>
- `if(typeof ${variableName} === 'undefined') { ${runtimeTemplate.throwMissingModuleErrorBlock(
- { request }
- )} }\n`;
- /**
- * Gets source for amd or umd external.
- * @param {ModuleId | string} id the module id
- * @param {boolean} optional true, if the module is optional
- * @param {string | string[]} request the request path
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {SourceData} the generated source
- */
- const getSourceForAmdOrUmdExternal = (
- id,
- optional,
- request,
- runtimeTemplate
- ) => {
- const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
- `${id}`
- )}__`;
- return {
- init: optional
- ? checkExternalVariable(
- externalVariable,
- Array.isArray(request) ? request.join(".") : request,
- runtimeTemplate
- )
- : undefined,
- expression: externalVariable
- };
- };
- /**
- * Gets source for default case.
- * @param {boolean} optional true, if the module is optional
- * @param {string | string[]} request the request path
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @returns {SourceData} the generated source
- */
- const getSourceForDefaultCase = (optional, request, runtimeTemplate) => {
- if (!Array.isArray(request)) {
- // make it an array as the look up works the same basically
- request = [request];
- }
- const variableName = request[0];
- const objectLookup = propertyAccess(request, 1);
- return {
- init: optional
- ? checkExternalVariable(variableName, request.join("."), runtimeTemplate)
- : undefined,
- expression: `${variableName}${objectLookup}`
- };
- };
- /** @typedef {Record<string, string | string[]>} RequestRecord */
- /** @typedef {string | string[] | RequestRecord} ExternalModuleRequest */
- const createCompilationHooks = () => ({
- /**
- * @type {SyncBailHook<[Chunk, Compilation], boolean>}
- * @since 5.106.0
- */
- chunkCondition: new SyncBailHook(["chunk", "compilation"])
- });
- /**
- * @typedef {ReturnType<typeof createCompilationHooks>} ExternalModuleHooks
- */
- /**
- * Defines the build info properties specific to external modules.
- * @typedef {object} KnownExternalModuleBuildInfo
- * @property {boolean=} javascriptModule true when emitting an ESM external (`output.module`)
- */
- /** @typedef {BuildInfo & KnownExternalModuleBuildInfo} ExternalModuleBuildInfo */
- class ExternalModule extends Module {
- /**
- * Creates an instance of ExternalModule.
- * @param {ExternalModuleRequest} request request
- * @param {ExternalsType} type type
- * @param {string} userRequest user request
- * @param {DependencyMeta=} dependencyMeta dependency meta
- * @param {ExternalInterop=} interop how the external's exports interoperate with ES module imports
- * @param {boolean=} sideEffects whether importing the external has side effects (undefined = assume it has)
- */
- constructor(
- request,
- type,
- userRequest,
- dependencyMeta,
- interop,
- sideEffects
- ) {
- super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, null);
- // Redeclared with the external module specific shape
- /** @type {ExternalModuleBuildInfo | undefined} */
- this.buildInfo = undefined;
- // Info from Factory
- /** @type {ExternalModuleRequest} */
- this.request = request;
- /** @type {ExternalsType} */
- this.externalType = type;
- /** @type {string} */
- this.userRequest = userRequest;
- /** @type {DependencyMeta=} */
- this.dependencyMeta = dependencyMeta;
- /** @type {ExternalInterop | undefined} interop shape of the external's exports (undefined = importer-driven default) */
- this.interop = interop;
- /** @type {boolean | undefined} declared side-effects state (undefined = assume side effects, webpack can't analyze an external) */
- this.sideEffects = sideEffects;
- if (sideEffects !== undefined) {
- this.factoryMeta = { sideEffectFree: !sideEffects };
- }
- }
- /**
- * Returns the source types this module can generate.
- * @returns {SourceTypes} types available (do not mutate)
- */
- getSourceTypes() {
- // resolved, so a type rendering no javascript is never reported as a
- // javascript module — that would emit a dead `false` factory in the chunk
- const type = this._resolveExternalType(this.externalType);
- // TODO webpack 6 drop "css-url" once the alias is removed
- if (type === ASSET_URL_TYPE || type === "css-url") {
- return ASSET_URL_TYPES;
- }
- if (type === "css-import") return CSS_IMPORT_TYPES;
- return JAVASCRIPT_TYPES;
- }
- /**
- * Gets the library identifier.
- * @param {LibIdentOptions} options options
- * @returns {LibIdent | null} an identifier for library inclusion
- */
- libIdent(options) {
- return this.userRequest;
- }
- /**
- * Returns true if the module can be placed in the chunk.
- * @param {Chunk} chunk the chunk which condition should be checked
- * @param {Compilation} compilation the compilation
- * @returns {boolean} true if the module can be placed in the chunk
- */
- chunkCondition(chunk, compilation) {
- const { chunkCondition } = ExternalModule.getCompilationHooks(compilation);
- const condition = chunkCondition.call(chunk, compilation);
- if (condition !== undefined) return condition;
- const type = this._resolveExternalType(this.externalType);
- // For `import()` externals, keep them in the initial chunk to avoid loading
- // them asynchronously twice and to improve runtime performance.
- if (["css-import", "module"].includes(type)) {
- return true;
- }
- return compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0;
- }
- /**
- * Gets side effects connection state.
- * @param {ModuleGraph} moduleGraph the module graph
- * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
- */
- getSideEffectsConnectionState(moduleGraph) {
- if (this.factoryMeta !== undefined) {
- if (this.factoryMeta.sideEffectFree) return false;
- if (this.factoryMeta.sideEffectFree === false) return true;
- }
- return true;
- }
- /**
- * Returns the unique identifier used to reference this module.
- * @returns {string} a unique identifier of the module
- */
- identifier() {
- let id = `external ${this._resolveExternalType(
- this.externalType
- )} ${JSON.stringify(this.request)}`;
- const meta = /** @type {ImportDependencyMeta | undefined} */ (
- this.dependencyMeta
- );
- if (meta) {
- if (meta.phase) {
- id += `|phase=${ImportPhaseUtils.stringify(meta.phase)}`;
- }
- if (meta.attributes) {
- id += `|attributes=${JSON.stringify(meta.attributes)}`;
- }
- }
- if (this.interop) id += `|interop=${this.interop}`;
- // two externals for the same target with a different side-effects state
- // must not be merged into one module
- if (this.sideEffects !== undefined) {
- id += `|sideEffects=${this.sideEffects}`;
- }
- return id;
- }
- /**
- * Returns a human-readable identifier for this module.
- * @param {RequestShortener} requestShortener the request shortener
- * @returns {string} a user readable identifier of the module
- */
- readableIdentifier(requestShortener) {
- return `external ${JSON.stringify(this.request)}`;
- }
- /**
- * Checks whether the module needs to be rebuilt for the current build state.
- * @param {NeedBuildContext} context context info
- * @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
- * @returns {void}
- */
- needBuild(context, callback) {
- return callback(null, !this.buildMeta);
- }
- /**
- * Builds the module using the provided compilation context.
- * @param {WebpackOptions} options webpack options
- * @param {Compilation} compilation the compilation
- * @param {ResolverWithOptions} resolver the resolver
- * @param {InputFileSystem} fs the file system
- * @param {BuildCallback} callback callback function
- * @returns {void}
- */
- build(options, compilation, resolver, fs, callback) {
- this.buildMeta = {
- async: false,
- exportsType: undefined
- };
- this.buildInfo = {
- strict: true,
- topLevelDeclarations: new Set(),
- javascriptModule: compilation.outputOptions.module
- };
- const { request, externalType } = this._getRequestAndExternalType();
- if (
- request === undefined &&
- typeof this.request === "object" &&
- !Array.isArray(this.request) &&
- !LIBRARY_WIRED_EXTERNAL_TYPES.has(this.externalType)
- ) {
- this.addError(
- new WebpackError(
- `Missing external configuration for type "${
- this.externalType
- }" in external ${JSON.stringify(
- this.request
- )}. Add a ${JSON.stringify(
- this.externalType
- )} entry to it or set 'output.externalsType'/'output.library.type' to one of: ${Object.keys(
- this.request
- )
- .map((key) => JSON.stringify(key))
- .join(", ")}`
- )
- );
- }
- this.buildMeta.exportsType = "dynamic";
- let canMangle = false;
- this.clearDependenciesAndBlocks();
- switch (externalType) {
- case "this":
- this.buildInfo.strict = false;
- break;
- case "system":
- if (!Array.isArray(request) || request.length === 1) {
- this.buildMeta.exportsType = "namespace";
- canMangle = true;
- }
- break;
- case "module":
- if (this.buildInfo.javascriptModule) {
- if (!Array.isArray(request) || request.length === 1) {
- this.buildMeta.exportsType = "namespace";
- canMangle = true;
- }
- } else {
- this.buildMeta.async = true;
- getEnvironmentNotSupportAsyncWarning().check(
- this,
- compilation.runtimeTemplate,
- "external module"
- );
- if (!Array.isArray(request) || request.length === 1) {
- this.buildMeta.exportsType = "namespace";
- canMangle = false;
- }
- }
- break;
- case "script":
- this.buildMeta.async = true;
- getEnvironmentNotSupportAsyncWarning().check(
- this,
- compilation.runtimeTemplate,
- "external script"
- );
- break;
- case "promise":
- this.buildMeta.async = true;
- getEnvironmentNotSupportAsyncWarning().check(
- this,
- compilation.runtimeTemplate,
- "external promise"
- );
- break;
- case "amd-async":
- this.buildMeta.async = true;
- getEnvironmentNotSupportAsyncWarning().check(
- this,
- compilation.runtimeTemplate,
- "external amd-async"
- );
- break;
- case "import":
- this.buildMeta.async = true;
- getEnvironmentNotSupportAsyncWarning().check(
- this,
- compilation.runtimeTemplate,
- "external import"
- );
- if (!Array.isArray(request) || request.length === 1) {
- this.buildMeta.exportsType = "namespace";
- canMangle = false;
- }
- break;
- }
- // Opt-in override for how the external's exports interoperate with ESM
- // imports, independent of the importer's strictness (see Rollup's
- // `output.interop`). Only meaningful for a single-request external.
- if (this.interop && (!Array.isArray(request) || request.length === 1)) {
- if (this.interop === "esModule") {
- // external already is an ES module namespace: `default` unboxes to `.default`
- this.buildMeta.exportsType = "namespace";
- } else {
- // "default": treat as CommonJS, `default` is the whole exports (Node.js semantics)
- this.buildMeta.exportsType = "default";
- this.buildMeta.defaultObject = "redirect";
- }
- canMangle = false;
- }
- this.addDependency(new StaticExportsDependency(true, canMangle));
- callback();
- }
- /**
- * restore unsafe cache data
- * @param {UnsafeCacheData} unsafeCacheData data from getUnsafeCacheData
- * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
- */
- restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
- this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
- }
- /**
- * Returns the reason this module cannot be concatenated, when one exists.
- * @param {ConcatenationBailoutReasonContext} context context
- * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
- */
- getConcatenationBailoutReason(context) {
- switch (this.externalType) {
- case "amd":
- case "amd-require":
- case "umd":
- case "umd2":
- case "system":
- case "jsonp":
- return `${this.externalType} externals can't be concatenated`;
- }
- return undefined;
- }
- /**
- * @returns {boolean} true, when it may be wrapped
- */
- canBeWrappedInConcatenation() {
- if (/** @type {BuildMeta} */ (this.buildMeta).async) {
- return false;
- }
- // every other synchronous type is a plain expression; only "module"
- // renders as a hoisted `import` declaration, and passing it the
- // concatenation scope is what narrows it to named specifiers
- return this._resolveExternalType(this.externalType) !== "module";
- }
- /**
- * Get request and external type.
- * @private
- * @returns {{ request: string | string[], externalType: ExternalsType }} the request and external type
- */
- _getRequestAndExternalType() {
- let { request, externalType } = this;
- if (typeof request === "object" && !Array.isArray(request)) {
- request = request[externalType];
- }
- externalType = this._resolveExternalType(externalType);
- return { request, externalType };
- }
- /**
- * Resolve the detailed external type from the raw external type.
- * e.g. resolve "module" or "import" from "module-import" type
- * @param {ExternalsType} externalType raw external type
- * @returns {ExternalsType} resolved external type
- */
- _resolveExternalType(externalType) {
- if (externalType === "module-import") {
- if (
- this.dependencyMeta &&
- /** @type {ImportDependencyMeta} */
- (this.dependencyMeta).externalType
- ) {
- return /** @type {ImportDependencyMeta} */ (this.dependencyMeta)
- .externalType;
- }
- return "module";
- } else if (
- // TODO webpack 6 drop "css-url" once the alias is removed
- externalType === "asset" ||
- externalType === ASSET_URL_TYPE ||
- externalType === "css-url"
- ) {
- // the consumer decides: a css `url()` reads the url out of the module
- // (marked by the factory), a `new URL()` requires the `asset` wrapper
- if (
- this.dependencyMeta &&
- /** @type {AssetDependencyMeta} */
- (this.dependencyMeta).sourceType
- ) {
- return /** @type {AssetDependencyMeta} */ (this.dependencyMeta)
- .sourceType;
- }
- return "asset";
- }
- return externalType;
- }
- /**
- * Returns the source data.
- * @private
- * @param {string | string[]} request request
- * @param {ExternalsType} externalType the external type
- * @param {RuntimeTemplate} runtimeTemplate the runtime template
- * @param {ModuleGraph} moduleGraph the module graph
- * @param {ChunkGraph} chunkGraph the chunk graph
- * @param {RuntimeSpec} runtime the runtime
- * @param {DependencyMeta | undefined} dependencyMeta the dependency meta
- * @param {ConcatenationScope=} concatenationScope concatenationScope
- * @returns {SourceData} the source data
- */
- _getSourceData(
- request,
- externalType,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- dependencyMeta,
- concatenationScope
- ) {
- request = normalizeNodeCoreModuleRequest(
- request,
- externalType,
- runtimeTemplate
- );
- switch (externalType) {
- case "this":
- case "window":
- case "self":
- return getSourceForGlobalVariableExternal(request, this.externalType);
- case "global":
- return getSourceForGlobalVariableExternal(
- request,
- runtimeTemplate.globalObject
- );
- case "commonjs":
- case "commonjs2":
- case "commonjs-module":
- case "commonjs-static":
- case "node-commonjs": {
- const { node } = runtimeTemplate.compilation.options.externalsPresets;
- // ESM has no `require`; load via `createRequire` when the target is node
- const createRequireInModule =
- /** @type {BuildInfo} */ (this.buildInfo).javascriptModule &&
- (externalType === "node-commonjs" || Boolean(node));
- if (!createRequireInModule) {
- return getSourceForCommonJsExternal(request);
- }
- // for a universal target (e.g. `["node", "web"]`) load defensively so the browser doesn't crash
- return getSourceForCommonJsExternalInNodeModule(
- request,
- runtimeTemplate,
- runtimeTemplate.isUniversalTarget()
- );
- }
- case "amd-async":
- return getSourceForAmdAsyncExternal(request, runtimeTemplate);
- case "amd":
- case "amd-require":
- case "umd":
- case "umd2":
- case "system":
- case "jsonp": {
- const id = chunkGraph.getModuleId(this);
- return getSourceForAmdOrUmdExternal(
- id !== null ? id : this.identifier(),
- this.isOptional(moduleGraph),
- request,
- runtimeTemplate
- );
- }
- case "import":
- return getSourceForImportExternal(
- request,
- runtimeTemplate,
- /** @type {ImportDependencyMeta} */ (dependencyMeta)
- );
- case "script":
- return getSourceForScriptExternal(request, runtimeTemplate);
- case "module": {
- if (!(/** @type {BuildInfo} */ (this.buildInfo).javascriptModule)) {
- if (!runtimeTemplate.supportsDynamicImport()) {
- throw new Error(
- `The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script${
- runtimeTemplate.supportsEcmaScriptModuleSyntax()
- ? "\nDid you mean to build a EcmaScript Module ('output.module: true')?"
- : ""
- }`
- );
- }
- return getSourceForImportExternal(
- request,
- runtimeTemplate,
- /** @type {ImportDependencyMeta} */ (dependencyMeta)
- );
- }
- if (!runtimeTemplate.supportsEcmaScriptModuleSyntax()) {
- throw new Error(
- "The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'"
- );
- }
- return getSourceForModuleExternal(
- request,
- moduleGraph.getExportsInfo(this),
- runtime,
- runtimeTemplate,
- /** @type {ImportDependencyMeta} */ (dependencyMeta),
- concatenationScope
- );
- }
- case "var":
- case "promise":
- case "assign":
- default:
- return getSourceForDefaultCase(
- this.isOptional(moduleGraph),
- request,
- runtimeTemplate
- );
- }
- }
- /**
- * Generates code and runtime requirements for this module.
- * @param {CodeGenerationContext} context context for code generation
- * @returns {CodeGenerationResult} result
- */
- codeGeneration({
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- concatenationScope
- }) {
- const { request, externalType } = this._getRequestAndExternalType();
- switch (externalType) {
- case "asset": {
- /** @type {Sources} */
- const sources = new Map();
- sources.set(
- JAVASCRIPT_TYPE,
- new RawSource(`module.exports = ${JSON.stringify(request)};`)
- );
- /** @type {CodeGenerationResultData} */
- const data = new Map();
- data.set("url", { javascript: /** @type {string} */ (request) });
- return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
- }
- // TODO webpack 6 remove "css-url" alias
- case "css-url":
- case "asset-url": {
- /** @type {Sources} */
- const sources = new Map();
- /** @type {CodeGenerationResultData} */
- const data = new Map();
- data.set("url", { [ASSET_URL_TYPE]: /** @type {string} */ (request) });
- return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
- }
- case "css-import": {
- /** @type {Sources} */
- const sources = new Map();
- const dependencyMeta = /** @type {CssImportDependencyMeta} */ (
- this.dependencyMeta
- );
- const layer =
- dependencyMeta.layer !== undefined
- ? ` layer(${dependencyMeta.layer})`
- : "";
- const supports = dependencyMeta.supports
- ? ` supports(${dependencyMeta.supports})`
- : "";
- const media = dependencyMeta.media ? ` ${dependencyMeta.media}` : "";
- sources.set(
- "css-import",
- new RawSource(
- `@import url(${JSON.stringify(
- request
- )})${layer}${supports}${media};`
- )
- );
- return {
- sources,
- runtimeRequirements: EMPTY_RUNTIME_REQUIREMENTS
- };
- }
- default: {
- // A wrapped external runs as a module body inside the wrapper, so it
- // renders the plain `module.exports =` form: its exports are read
- // through the wrapper accessor, not through a shared-scope binding.
- const wrapped = Boolean(
- concatenationScope &&
- /** @type {ConcatenationScope} */ (concatenationScope).isWrapped()
- );
- const sourceData = this._getSourceData(
- request,
- externalType,
- runtimeTemplate,
- moduleGraph,
- chunkGraph,
- runtime,
- this.dependencyMeta,
- wrapped ? undefined : concatenationScope
- );
- // sourceString can be empty str only when there is concatenationScope
- let sourceString = sourceData.expression;
- if (sourceData.iife) {
- sourceString = `(function() { return ${sourceString}; }())`;
- }
- const specifiers = sourceData.specifiers;
- if (specifiers) {
- sourceString = "";
- const scope = /** @type {ConcatenationScope} */ (concatenationScope);
- for (const [specifier, finalName] of specifiers) {
- // the hoisted `import { x as finalName }` binding is a top-level
- // name of the chunk, reserve it before members get renamed
- scope.usedNames.add(finalName);
- scope.registerRawExport(specifier, finalName);
- }
- } else if (concatenationScope && !wrapped) {
- sourceString = `${runtimeTemplate.renderConst()} ${
- ConcatenationScope.NAMESPACE_OBJECT_EXPORT
- } = ${sourceString};`;
- concatenationScope.registerNamespaceExport(
- ConcatenationScope.NAMESPACE_OBJECT_EXPORT
- );
- } else {
- sourceString = `module.exports = ${sourceString};`;
- }
- if (sourceData.init) {
- sourceString = `${sourceData.init}\n${sourceString}`;
- }
- /** @type {undefined | CodeGenerationResultData} */
- let data;
- if (sourceData.chunkInitFragments) {
- data = new Map();
- data.set("chunkInitFragments", sourceData.chunkInitFragments);
- }
- /** @type {Sources} */
- const sources = new Map();
- if (this.useSourceMap || this.useSimpleSourceMap) {
- sources.set(
- JAVASCRIPT_TYPE,
- new OriginalSource(sourceString, this.identifier())
- );
- } else {
- sources.set(JAVASCRIPT_TYPE, new RawSource(sourceString));
- }
- let runtimeRequirements = sourceData.runtimeRequirements;
- if (!concatenationScope) {
- if (!runtimeRequirements) {
- runtimeRequirements = RUNTIME_REQUIREMENTS;
- } else {
- const set = new Set(runtimeRequirements);
- set.add(RuntimeGlobals.module);
- runtimeRequirements = set;
- }
- }
- return {
- sources,
- runtimeRequirements:
- runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
- data
- };
- }
- }
- }
- /**
- * Returns the estimated size for the requested source type.
- * @param {string=} type the source type for which the size should be estimated
- * @returns {number} the estimated size of the module (must be non-zero)
- */
- size(type) {
- return 42;
- }
- /**
- * Updates the hash with the data contributed by this instance.
- * @param {Hash} hash the hash used to track dependencies
- * @param {UpdateHashContext} context context
- * @returns {void}
- */
- updateHash(hash, context) {
- const { chunkGraph } = context;
- hash.update(
- `${this._resolveExternalType(this.externalType)}${JSON.stringify(
- this.request
- )}${this.isOptional(chunkGraph.moduleGraph)}`
- );
- const meta = /** @type {ImportDependencyMeta | undefined} */ (
- this.dependencyMeta
- );
- if (meta) {
- if (meta.phase) {
- hash.update(`|phase=${ImportPhaseUtils.stringify(meta.phase)}`);
- }
- if (meta.attributes) {
- hash.update(`|attributes=${JSON.stringify(meta.attributes)}`);
- }
- }
- if (this.interop) hash.update(`|interop=${this.interop}`);
- if (this.sideEffects !== undefined) {
- hash.update(`|sideEffects=${this.sideEffects}`);
- }
- super.updateHash(hash, context);
- }
- /**
- * Serializes this instance into the provided serializer context.
- * @param {ObjectSerializerContext} context context
- */
- serialize(context) {
- context
- .write(this.request)
- .write(this.externalType)
- .write(this.userRequest)
- .write(this.dependencyMeta)
- .write(this.interop)
- .write(this.sideEffects);
- super.serialize(context);
- }
- /**
- * Restores this instance from the provided deserializer context.
- * @param {ObjectDeserializerContext} context context
- */
- deserialize(context) {
- this.request = context.read();
- const c1 = context.rest;
- this.externalType = c1.read();
- const c2 = c1.rest;
- this.userRequest = c2.read();
- const c3 = c2.rest;
- this.dependencyMeta = c3.read();
- const c4 = c3.rest;
- this.interop = c4.read();
- const c5 = c4.rest;
- this.sideEffects = c5.read();
- super.deserialize(c5.rest);
- }
- }
- ExternalModule.getCompilationHooks = createHooksRegistry(
- createCompilationHooks
- );
- makeSerializable(ExternalModule, "webpack/lib/ExternalModule");
- ExternalModule.ModuleExternalInitFragment = ModuleExternalInitFragment;
- ExternalModule.getExternalModuleNodeCommonjsInitFragment =
- getExternalModuleNodeCommonjsInitFragment;
- module.exports = ExternalModule;
|