UNPKG

22.5 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { OriginalSource, RawSource } = require("webpack-sources");
9const ConcatenationScope = require("./ConcatenationScope");
10const { UsageState } = require("./ExportsInfo");
11const InitFragment = require("./InitFragment");
12const Module = require("./Module");
13const RuntimeGlobals = require("./RuntimeGlobals");
14const Template = require("./Template");
15const StaticExportsDependency = require("./dependencies/StaticExportsDependency");
16const createHash = require("./util/createHash");
17const extractUrlAndGlobal = require("./util/extractUrlAndGlobal");
18const makeSerializable = require("./util/makeSerializable");
19const propertyAccess = require("./util/propertyAccess");
20const { register } = require("./util/serialization");
21
22/** @typedef {import("webpack-sources").Source} Source */
23/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
24/** @typedef {import("./Chunk")} Chunk */
25/** @typedef {import("./ChunkGraph")} ChunkGraph */
26/** @typedef {import("./Compilation")} Compilation */
27/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
28/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
29/** @typedef {import("./ExportsInfo")} ExportsInfo */
30/** @typedef {import("./Module").CodeGenerationContext} CodeGenerationContext */
31/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
32/** @typedef {import("./Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
33/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
34/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
35/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
36/** @typedef {import("./RequestShortener")} RequestShortener */
37/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
38/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
39/** @typedef {import("./WebpackError")} WebpackError */
40/** @typedef {import("./javascript/JavascriptModulesPlugin").ChunkRenderContext} ChunkRenderContext */
41/** @typedef {import("./util/Hash")} Hash */
42/** @typedef {typeof import("./util/Hash")} HashConstructor */
43/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
44/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
45
46/**
47 * @typedef {Object} SourceData
48 * @property {boolean=} iife
49 * @property {string=} init
50 * @property {string} expression
51 * @property {InitFragment<ChunkRenderContext>[]=} chunkInitFragments
52 * @property {ReadonlySet<string>=} runtimeRequirements
53 */
54
55const TYPES = new Set(["javascript"]);
56const CSS_TYPES = new Set(["css-import"]);
57const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
58const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]);
59const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([
60 RuntimeGlobals.definePropertyGetters
61]);
62const EMPTY_RUNTIME_REQUIREMENTS = new Set([]);
63
64/**
65 * @param {string|string[]} variableName the variable name or path
66 * @param {string} type the module system
67 * @returns {SourceData} the generated source
68 */
69const getSourceForGlobalVariableExternal = (variableName, type) => {
70 if (!Array.isArray(variableName)) {
71 // make it an array as the look up works the same basically
72 variableName = [variableName];
73 }
74
75 // needed for e.g. window["some"]["thing"]
76 const objectLookup = variableName.map(r => `[${JSON.stringify(r)}]`).join("");
77 return {
78 iife: type === "this",
79 expression: `${type}${objectLookup}`
80 };
81};
82
83/**
84 * @param {string|string[]} moduleAndSpecifiers the module request
85 * @returns {SourceData} the generated source
86 */
87const getSourceForCommonJsExternal = moduleAndSpecifiers => {
88 if (!Array.isArray(moduleAndSpecifiers)) {
89 return {
90 expression: `require(${JSON.stringify(moduleAndSpecifiers)})`
91 };
92 }
93 const moduleName = moduleAndSpecifiers[0];
94 return {
95 expression: `require(${JSON.stringify(moduleName)})${propertyAccess(
96 moduleAndSpecifiers,
97 1
98 )}`
99 };
100};
101
102/**
103 * @param {string|string[]} moduleAndSpecifiers the module request
104 * @returns {SourceData} the generated source
105 */
106const getSourceForCommonJsExternalInNodeModule = moduleAndSpecifiers => {
107 const chunkInitFragments = [
108 new InitFragment(
109 'import { createRequire as __WEBPACK_EXTERNAL_createRequire } from "module";\n',
110 InitFragment.STAGE_HARMONY_IMPORTS,
111 0,
112 "external module node-commonjs"
113 )
114 ];
115 if (!Array.isArray(moduleAndSpecifiers)) {
116 return {
117 expression: `__WEBPACK_EXTERNAL_createRequire(import.meta.url)(${JSON.stringify(
118 moduleAndSpecifiers
119 )})`,
120 chunkInitFragments
121 };
122 }
123 const moduleName = moduleAndSpecifiers[0];
124 return {
125 expression: `__WEBPACK_EXTERNAL_createRequire(import.meta.url)(${JSON.stringify(
126 moduleName
127 )})${propertyAccess(moduleAndSpecifiers, 1)}`,
128 chunkInitFragments
129 };
130};
131
132/**
133 * @param {string|string[]} moduleAndSpecifiers the module request
134 * @param {RuntimeTemplate} runtimeTemplate the runtime template
135 * @returns {SourceData} the generated source
136 */
137const getSourceForImportExternal = (moduleAndSpecifiers, runtimeTemplate) => {
138 const importName = runtimeTemplate.outputOptions.importFunctionName;
139 if (!runtimeTemplate.supportsDynamicImport() && importName === "import") {
140 throw new Error(
141 "The target environment doesn't support 'import()' so it's not possible to use external type 'import'"
142 );
143 }
144 if (!Array.isArray(moduleAndSpecifiers)) {
145 return {
146 expression: `${importName}(${JSON.stringify(moduleAndSpecifiers)});`
147 };
148 }
149 if (moduleAndSpecifiers.length === 1) {
150 return {
151 expression: `${importName}(${JSON.stringify(moduleAndSpecifiers[0])});`
152 };
153 }
154 const moduleName = moduleAndSpecifiers[0];
155 return {
156 expression: `${importName}(${JSON.stringify(
157 moduleName
158 )}).then(${runtimeTemplate.returningFunction(
159 `module${propertyAccess(moduleAndSpecifiers, 1)}`,
160 "module"
161 )});`
162 };
163};
164
165class ModuleExternalInitFragment extends InitFragment {
166 /**
167 * @param {string} request import source
168 * @param {string=} ident recomputed ident
169 * @param {string | HashConstructor=} hashFunction the hash function to use
170 */
171 constructor(request, ident, hashFunction = "md4") {
172 if (ident === undefined) {
173 ident = Template.toIdentifier(request);
174 if (ident !== request) {
175 ident += `_${createHash(hashFunction)
176 .update(request)
177 .digest("hex")
178 .slice(0, 8)}`;
179 }
180 }
181 const identifier = `__WEBPACK_EXTERNAL_MODULE_${ident}__`;
182 super(
183 `import * as ${identifier} from ${JSON.stringify(request)};\n`,
184 InitFragment.STAGE_HARMONY_IMPORTS,
185 0,
186 `external module import ${ident}`
187 );
188 this._ident = ident;
189 this._identifier = identifier;
190 this._request = request;
191 }
192
193 getNamespaceIdentifier() {
194 return this._identifier;
195 }
196}
197
198register(
199 ModuleExternalInitFragment,
200 "webpack/lib/ExternalModule",
201 "ModuleExternalInitFragment",
202 {
203 serialize(obj, { write }) {
204 write(obj._request);
205 write(obj._ident);
206 },
207 deserialize({ read }) {
208 return new ModuleExternalInitFragment(read(), read());
209 }
210 }
211);
212
213const generateModuleRemapping = (input, exportsInfo, runtime) => {
214 if (exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused) {
215 const properties = [];
216 for (const exportInfo of exportsInfo.orderedExports) {
217 const used = exportInfo.getUsedName(exportInfo.name, runtime);
218 if (!used) continue;
219 const nestedInfo = exportInfo.getNestedExportsInfo();
220 if (nestedInfo) {
221 const nestedExpr = generateModuleRemapping(
222 `${input}${propertyAccess([exportInfo.name])}`,
223 nestedInfo
224 );
225 if (nestedExpr) {
226 properties.push(`[${JSON.stringify(used)}]: y(${nestedExpr})`);
227 continue;
228 }
229 }
230 properties.push(
231 `[${JSON.stringify(used)}]: () => ${input}${propertyAccess([
232 exportInfo.name
233 ])}`
234 );
235 }
236 return `x({ ${properties.join(", ")} })`;
237 }
238};
239
240/**
241 * @param {string|string[]} moduleAndSpecifiers the module request
242 * @param {ExportsInfo} exportsInfo exports info of this module
243 * @param {RuntimeSpec} runtime the runtime
244 * @param {string | HashConstructor=} hashFunction the hash function to use
245 * @returns {SourceData} the generated source
246 */
247const getSourceForModuleExternal = (
248 moduleAndSpecifiers,
249 exportsInfo,
250 runtime,
251 hashFunction
252) => {
253 if (!Array.isArray(moduleAndSpecifiers))
254 moduleAndSpecifiers = [moduleAndSpecifiers];
255 const initFragment = new ModuleExternalInitFragment(
256 moduleAndSpecifiers[0],
257 undefined,
258 hashFunction
259 );
260 const baseAccess = `${initFragment.getNamespaceIdentifier()}${propertyAccess(
261 moduleAndSpecifiers,
262 1
263 )}`;
264 const moduleRemapping = generateModuleRemapping(
265 baseAccess,
266 exportsInfo,
267 runtime
268 );
269 let expression = moduleRemapping || baseAccess;
270 return {
271 expression,
272 init: `var x = y => { var x = {}; ${RuntimeGlobals.definePropertyGetters}(x, y); return x; }\nvar y = x => () => x`,
273 runtimeRequirements: moduleRemapping
274 ? RUNTIME_REQUIREMENTS_FOR_MODULE
275 : undefined,
276 chunkInitFragments: [initFragment]
277 };
278};
279
280/**
281 * @param {string|string[]} urlAndGlobal the script request
282 * @param {RuntimeTemplate} runtimeTemplate the runtime template
283 * @returns {SourceData} the generated source
284 */
285const getSourceForScriptExternal = (urlAndGlobal, runtimeTemplate) => {
286 if (typeof urlAndGlobal === "string") {
287 urlAndGlobal = extractUrlAndGlobal(urlAndGlobal);
288 }
289 const url = urlAndGlobal[0];
290 const globalName = urlAndGlobal[1];
291 return {
292 init: "var __webpack_error__ = new Error();",
293 expression: `new Promise(${runtimeTemplate.basicFunction(
294 "resolve, reject",
295 [
296 `if(typeof ${globalName} !== "undefined") return resolve();`,
297 `${RuntimeGlobals.loadScript}(${JSON.stringify(
298 url
299 )}, ${runtimeTemplate.basicFunction("event", [
300 `if(typeof ${globalName} !== "undefined") return resolve();`,
301 "var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
302 "var realSrc = event && event.target && event.target.src;",
303 "__webpack_error__.message = 'Loading script failed.\\n(' + errorType + ': ' + realSrc + ')';",
304 "__webpack_error__.name = 'ScriptExternalLoadError';",
305 "__webpack_error__.type = errorType;",
306 "__webpack_error__.request = realSrc;",
307 "reject(__webpack_error__);"
308 ])}, ${JSON.stringify(globalName)});`
309 ]
310 )}).then(${runtimeTemplate.returningFunction(
311 `${globalName}${propertyAccess(urlAndGlobal, 2)}`
312 )})`,
313 runtimeRequirements: RUNTIME_REQUIREMENTS_FOR_SCRIPT
314 };
315};
316
317/**
318 * @param {string} variableName the variable name to check
319 * @param {string} request the request path
320 * @param {RuntimeTemplate} runtimeTemplate the runtime template
321 * @returns {string} the generated source
322 */
323const checkExternalVariable = (variableName, request, runtimeTemplate) => {
324 return `if(typeof ${variableName} === 'undefined') { ${runtimeTemplate.throwMissingModuleErrorBlock(
325 { request }
326 )} }\n`;
327};
328
329/**
330 * @param {string|number} id the module id
331 * @param {boolean} optional true, if the module is optional
332 * @param {string|string[]} request the request path
333 * @param {RuntimeTemplate} runtimeTemplate the runtime template
334 * @returns {SourceData} the generated source
335 */
336const getSourceForAmdOrUmdExternal = (
337 id,
338 optional,
339 request,
340 runtimeTemplate
341) => {
342 const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
343 `${id}`
344 )}__`;
345 return {
346 init: optional
347 ? checkExternalVariable(
348 externalVariable,
349 Array.isArray(request) ? request.join(".") : request,
350 runtimeTemplate
351 )
352 : undefined,
353 expression: externalVariable
354 };
355};
356
357/**
358 * @param {boolean} optional true, if the module is optional
359 * @param {string|string[]} request the request path
360 * @param {RuntimeTemplate} runtimeTemplate the runtime template
361 * @returns {SourceData} the generated source
362 */
363const getSourceForDefaultCase = (optional, request, runtimeTemplate) => {
364 if (!Array.isArray(request)) {
365 // make it an array as the look up works the same basically
366 request = [request];
367 }
368
369 const variableName = request[0];
370 const objectLookup = propertyAccess(request, 1);
371 return {
372 init: optional
373 ? checkExternalVariable(variableName, request.join("."), runtimeTemplate)
374 : undefined,
375 expression: `${variableName}${objectLookup}`
376 };
377};
378
379class ExternalModule extends Module {
380 constructor(request, type, userRequest) {
381 super("javascript/dynamic", null);
382
383 // Info from Factory
384 /** @type {string | string[] | Record<string, string | string[]>} */
385 this.request = request;
386 /** @type {string} */
387 this.externalType = type;
388 /** @type {string} */
389 this.userRequest = userRequest;
390 }
391
392 /**
393 * @returns {Set<string>} types available (do not mutate)
394 */
395 getSourceTypes() {
396 return this.externalType === "css-import" ? CSS_TYPES : TYPES;
397 }
398
399 /**
400 * @param {LibIdentOptions} options options
401 * @returns {string | null} an identifier for library inclusion
402 */
403 libIdent(options) {
404 return this.userRequest;
405 }
406
407 /**
408 * @param {Chunk} chunk the chunk which condition should be checked
409 * @param {Compilation} compilation the compilation
410 * @returns {boolean} true, if the chunk is ok for the module
411 */
412 chunkCondition(chunk, { chunkGraph }) {
413 return this.externalType === "css-import"
414 ? true
415 : chunkGraph.getNumberOfEntryModules(chunk) > 0;
416 }
417
418 /**
419 * @returns {string} a unique identifier of the module
420 */
421 identifier() {
422 return `external ${this.externalType} ${JSON.stringify(this.request)}`;
423 }
424
425 /**
426 * @param {RequestShortener} requestShortener the request shortener
427 * @returns {string} a user readable identifier of the module
428 */
429 readableIdentifier(requestShortener) {
430 return "external " + JSON.stringify(this.request);
431 }
432
433 /**
434 * @param {NeedBuildContext} context context info
435 * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
436 * @returns {void}
437 */
438 needBuild(context, callback) {
439 return callback(null, !this.buildMeta);
440 }
441
442 /**
443 * @param {WebpackOptions} options webpack options
444 * @param {Compilation} compilation the compilation
445 * @param {ResolverWithOptions} resolver the resolver
446 * @param {InputFileSystem} fs the file system
447 * @param {function(WebpackError=): void} callback callback function
448 * @returns {void}
449 */
450 build(options, compilation, resolver, fs, callback) {
451 this.buildMeta = {
452 async: false,
453 exportsType: undefined
454 };
455 this.buildInfo = {
456 strict: true,
457 topLevelDeclarations: new Set(),
458 module: compilation.outputOptions.module
459 };
460 const { request, externalType } = this._getRequestAndExternalType();
461 this.buildMeta.exportsType = "dynamic";
462 let canMangle = false;
463 this.clearDependenciesAndBlocks();
464 switch (externalType) {
465 case "this":
466 this.buildInfo.strict = false;
467 break;
468 case "system":
469 if (!Array.isArray(request) || request.length === 1) {
470 this.buildMeta.exportsType = "namespace";
471 canMangle = true;
472 }
473 break;
474 case "module":
475 if (this.buildInfo.module) {
476 if (!Array.isArray(request) || request.length === 1) {
477 this.buildMeta.exportsType = "namespace";
478 canMangle = true;
479 }
480 } else {
481 this.buildMeta.async = true;
482 if (!Array.isArray(request) || request.length === 1) {
483 this.buildMeta.exportsType = "namespace";
484 canMangle = false;
485 }
486 }
487 break;
488 case "script":
489 case "promise":
490 this.buildMeta.async = true;
491 break;
492 case "import":
493 this.buildMeta.async = true;
494 if (!Array.isArray(request) || request.length === 1) {
495 this.buildMeta.exportsType = "namespace";
496 canMangle = false;
497 }
498 break;
499 }
500 this.addDependency(new StaticExportsDependency(true, canMangle));
501 callback();
502 }
503
504 restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
505 this._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
506 }
507
508 /**
509 * @param {ConcatenationBailoutReasonContext} context context
510 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
511 */
512 getConcatenationBailoutReason({ moduleGraph }) {
513 switch (this.externalType) {
514 case "amd":
515 case "amd-require":
516 case "umd":
517 case "umd2":
518 case "system":
519 case "jsonp":
520 return `${this.externalType} externals can't be concatenated`;
521 }
522 return undefined;
523 }
524
525 _getRequestAndExternalType() {
526 let { request, externalType } = this;
527 if (typeof request === "object" && !Array.isArray(request))
528 request = request[externalType];
529 return { request, externalType };
530 }
531
532 _getSourceData(
533 request,
534 externalType,
535 runtimeTemplate,
536 moduleGraph,
537 chunkGraph,
538 runtime
539 ) {
540 switch (externalType) {
541 case "this":
542 case "window":
543 case "self":
544 return getSourceForGlobalVariableExternal(request, this.externalType);
545 case "global":
546 return getSourceForGlobalVariableExternal(
547 request,
548 runtimeTemplate.globalObject
549 );
550 case "commonjs":
551 case "commonjs2":
552 case "commonjs-module":
553 case "commonjs-static":
554 return getSourceForCommonJsExternal(request);
555 case "node-commonjs":
556 return this.buildInfo.module
557 ? getSourceForCommonJsExternalInNodeModule(request)
558 : getSourceForCommonJsExternal(request);
559 case "amd":
560 case "amd-require":
561 case "umd":
562 case "umd2":
563 case "system":
564 case "jsonp": {
565 const id = chunkGraph.getModuleId(this);
566 return getSourceForAmdOrUmdExternal(
567 id !== null ? id : this.identifier(),
568 this.isOptional(moduleGraph),
569 request,
570 runtimeTemplate
571 );
572 }
573 case "import":
574 return getSourceForImportExternal(request, runtimeTemplate);
575 case "script":
576 return getSourceForScriptExternal(request, runtimeTemplate);
577 case "module": {
578 if (!this.buildInfo.module) {
579 if (!runtimeTemplate.supportsDynamicImport()) {
580 throw new Error(
581 "The target environment doesn't support dynamic import() syntax so it's not possible to use external type 'module' within a script" +
582 (runtimeTemplate.supportsEcmaScriptModuleSyntax()
583 ? "\nDid you mean to build a EcmaScript Module ('output.module: true')?"
584 : "")
585 );
586 }
587 return getSourceForImportExternal(request, runtimeTemplate);
588 }
589 if (!runtimeTemplate.supportsEcmaScriptModuleSyntax()) {
590 throw new Error(
591 "The target environment doesn't support EcmaScriptModule syntax so it's not possible to use external type 'module'"
592 );
593 }
594 return getSourceForModuleExternal(
595 request,
596 moduleGraph.getExportsInfo(this),
597 runtime,
598 runtimeTemplate.outputOptions.hashFunction
599 );
600 }
601 case "var":
602 case "promise":
603 case "const":
604 case "let":
605 case "assign":
606 default:
607 return getSourceForDefaultCase(
608 this.isOptional(moduleGraph),
609 request,
610 runtimeTemplate
611 );
612 }
613 }
614
615 /**
616 * @param {CodeGenerationContext} context context for code generation
617 * @returns {CodeGenerationResult} result
618 */
619 codeGeneration({
620 runtimeTemplate,
621 moduleGraph,
622 chunkGraph,
623 runtime,
624 concatenationScope
625 }) {
626 const { request, externalType } = this._getRequestAndExternalType();
627 switch (externalType) {
628 case "asset": {
629 const sources = new Map();
630 sources.set(
631 "javascript",
632 new RawSource(`module.exports = ${JSON.stringify(request)};`)
633 );
634 const data = new Map();
635 data.set("url", request);
636 return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
637 }
638 case "css-import": {
639 const sources = new Map();
640 sources.set(
641 "css-import",
642 new RawSource(`@import url(${JSON.stringify(request)});`)
643 );
644 return {
645 sources,
646 runtimeRequirements: EMPTY_RUNTIME_REQUIREMENTS
647 };
648 }
649 default: {
650 const sourceData = this._getSourceData(
651 request,
652 externalType,
653 runtimeTemplate,
654 moduleGraph,
655 chunkGraph,
656 runtime
657 );
658
659 let sourceString = sourceData.expression;
660 if (sourceData.iife)
661 sourceString = `(function() { return ${sourceString}; }())`;
662 if (concatenationScope) {
663 sourceString = `${
664 runtimeTemplate.supportsConst() ? "const" : "var"
665 } ${ConcatenationScope.NAMESPACE_OBJECT_EXPORT} = ${sourceString};`;
666 concatenationScope.registerNamespaceExport(
667 ConcatenationScope.NAMESPACE_OBJECT_EXPORT
668 );
669 } else {
670 sourceString = `module.exports = ${sourceString};`;
671 }
672 if (sourceData.init)
673 sourceString = `${sourceData.init}\n${sourceString}`;
674
675 let data = undefined;
676 if (sourceData.chunkInitFragments) {
677 data = new Map();
678 data.set("chunkInitFragments", sourceData.chunkInitFragments);
679 }
680
681 const sources = new Map();
682 if (this.useSourceMap || this.useSimpleSourceMap) {
683 sources.set(
684 "javascript",
685 new OriginalSource(sourceString, this.identifier())
686 );
687 } else {
688 sources.set("javascript", new RawSource(sourceString));
689 }
690
691 let runtimeRequirements = sourceData.runtimeRequirements;
692 if (!concatenationScope) {
693 if (!runtimeRequirements) {
694 runtimeRequirements = RUNTIME_REQUIREMENTS;
695 } else {
696 const set = new Set(runtimeRequirements);
697 set.add(RuntimeGlobals.module);
698 runtimeRequirements = set;
699 }
700 }
701
702 return {
703 sources,
704 runtimeRequirements:
705 runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
706 data
707 };
708 }
709 }
710 }
711
712 /**
713 * @param {string=} type the source type for which the size should be estimated
714 * @returns {number} the estimated size of the module (must be non-zero)
715 */
716 size(type) {
717 return 42;
718 }
719
720 /**
721 * @param {Hash} hash the hash used to track dependencies
722 * @param {UpdateHashContext} context context
723 * @returns {void}
724 */
725 updateHash(hash, context) {
726 const { chunkGraph } = context;
727 hash.update(
728 `${this.externalType}${JSON.stringify(this.request)}${this.isOptional(
729 chunkGraph.moduleGraph
730 )}`
731 );
732 super.updateHash(hash, context);
733 }
734
735 serialize(context) {
736 const { write } = context;
737
738 write(this.request);
739 write(this.externalType);
740 write(this.userRequest);
741
742 super.serialize(context);
743 }
744
745 deserialize(context) {
746 const { read } = context;
747
748 this.request = read();
749 this.externalType = read();
750 this.userRequest = read();
751
752 super.deserialize(context);
753 }
754}
755
756makeSerializable(ExternalModule, "webpack/lib/ExternalModule");
757
758module.exports = ExternalModule;