ExternalModule.js 24 KB

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