RemoteRuntimeModule.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const RuntimeGlobals = require("../RuntimeGlobals");
  7. const RuntimeModule = require("../RuntimeModule");
  8. const Template = require("../Template");
  9. /** @typedef {import("../Chunk")} Chunk */
  10. /** @typedef {import("./RemoteModule")} RemoteModule */
  11. class RemoteRuntimeModule extends RuntimeModule {
  12. constructor() {
  13. super("remotes loading");
  14. }
  15. /**
  16. * @returns {string | null} runtime code
  17. */
  18. generate() {
  19. const { compilation, chunkGraph } = this;
  20. const { runtimeTemplate, moduleGraph } = compilation;
  21. const chunkToRemotesMapping = {};
  22. const idToExternalAndNameMapping = {};
  23. for (const chunk of this.chunk.getAllAsyncChunks()) {
  24. const modules = chunkGraph.getChunkModulesIterableBySourceType(
  25. chunk,
  26. "remote"
  27. );
  28. if (!modules) continue;
  29. const remotes = (chunkToRemotesMapping[chunk.id] = []);
  30. for (const m of modules) {
  31. const module = /** @type {RemoteModule} */ (m);
  32. const name = module.internalRequest;
  33. const id = chunkGraph.getModuleId(module);
  34. const shareScope = module.shareScope;
  35. const dep = module.dependencies[0];
  36. const externalModule = moduleGraph.getModule(dep);
  37. const externalModuleId =
  38. externalModule && chunkGraph.getModuleId(externalModule);
  39. remotes.push(id);
  40. idToExternalAndNameMapping[id] = [shareScope, name, externalModuleId];
  41. }
  42. }
  43. return Template.asString([
  44. `var chunkMapping = ${JSON.stringify(
  45. chunkToRemotesMapping,
  46. null,
  47. "\t"
  48. )};`,
  49. `var idToExternalAndNameMapping = ${JSON.stringify(
  50. idToExternalAndNameMapping,
  51. null,
  52. "\t"
  53. )};`,
  54. `${
  55. RuntimeGlobals.ensureChunkHandlers
  56. }.remotes = ${runtimeTemplate.basicFunction("chunkId, promises", [
  57. `if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
  58. Template.indent([
  59. `chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction("id", [
  60. `var getScope = ${RuntimeGlobals.currentRemoteGetScope};`,
  61. "if(!getScope) getScope = [];",
  62. "var data = idToExternalAndNameMapping[id];",
  63. "if(getScope.indexOf(data) >= 0) return;",
  64. "getScope.push(data);",
  65. `if(data.p) return promises.push(data.p);`,
  66. `var onError = ${runtimeTemplate.basicFunction("error", [
  67. 'if(!error) error = new Error("Container missing");',
  68. 'if(typeof error.message === "string")',
  69. Template.indent(
  70. `error.message += '\\nwhile loading "' + data[1] + '" from ' + data[2];`
  71. ),
  72. `${
  73. RuntimeGlobals.moduleFactories
  74. }[id] = ${runtimeTemplate.basicFunction("", ["throw error;"])}`,
  75. "data.p = 0;"
  76. ])};`,
  77. `var handleFunction = ${runtimeTemplate.basicFunction(
  78. "fn, arg1, arg2, d, next, first",
  79. [
  80. "try {",
  81. Template.indent([
  82. "var promise = fn(arg1, arg2);",
  83. "if(promise && promise.then) {",
  84. Template.indent([
  85. `var p = promise.then(${runtimeTemplate.returningFunction(
  86. "next(result, d)",
  87. "result"
  88. )}, onError);`,
  89. `if(first) promises.push(data.p = p); else return p;`
  90. ]),
  91. "} else {",
  92. Template.indent(["return next(promise, d, first);"]),
  93. "}"
  94. ]),
  95. "} catch(error) {",
  96. Template.indent(["onError(error);"]),
  97. "}"
  98. ]
  99. )}`,
  100. `var onExternal = ${runtimeTemplate.returningFunction(
  101. `external ? handleFunction(${RuntimeGlobals.initializeSharing}, data[0], 0, external, onInitialized, first) : onError()`,
  102. "external, _, first"
  103. )};`,
  104. `var onInitialized = ${runtimeTemplate.returningFunction(
  105. `handleFunction(external.get, data[1], getScope, 0, onFactory, first)`,
  106. "_, external, first"
  107. )};`,
  108. `var onFactory = ${runtimeTemplate.basicFunction("factory", [
  109. "data.p = 1;",
  110. `${
  111. RuntimeGlobals.moduleFactories
  112. }[id] = ${runtimeTemplate.basicFunction("module", [
  113. "module.exports = factory();"
  114. ])}`
  115. ])};`,
  116. `handleFunction(${RuntimeGlobals.require}, data[2], 0, 0, onExternal, 1);`
  117. ])});`
  118. ]),
  119. "}"
  120. ])}`
  121. ]);
  122. }
  123. }
  124. module.exports = RemoteRuntimeModule;