RemoteModule.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
  4. */
  5. "use strict";
  6. const { RawSource } = require("webpack-sources");
  7. const Module = require("../Module");
  8. const {
  9. JAVASCRIPT_TYPES,
  10. REMOTE_AND_SHARE_INIT_TYPES
  11. } = require("../ModuleSourceTypeConstants");
  12. const { WEBPACK_MODULE_TYPE_REMOTE } = require("../ModuleTypeConstants");
  13. const RuntimeGlobals = require("../RuntimeGlobals");
  14. const makeSerializable = require("../util/makeSerializable");
  15. const FallbackDependency = require("./FallbackDependency");
  16. const RemoteToExternalDependency = require("./RemoteToExternalDependency");
  17. /**
  18. * @import {
  19. * WebpackOptionsNormalizedWithDefaults as WebpackOptions
  20. * } from "../config/defaults"
  21. */
  22. /** @import Compilation from "../Compilation" */
  23. /**
  24. * @import {
  25. * BuildCallback,
  26. * CodeGenerationContext,
  27. * CodeGenerationResultData,
  28. * CodeGenerationResult,
  29. * LibIdentOptions,
  30. * LibIdent,
  31. * NameForCondition,
  32. * NeedBuildCallback,
  33. * NeedBuildContext,
  34. * Sources,
  35. * SourceTypes,
  36. * ExportsType,
  37. * BasicSourceTypes
  38. * } from "../Module"
  39. */
  40. /** @import ModuleGraph from "../ModuleGraph" */
  41. /** @import RequestShortener from "../RequestShortener" */
  42. /** @import { ResolverWithOptions } from "../ResolverFactory" */
  43. /** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext<[string, ExternalRequests, string, string]>} ObjectDeserializerContext */
  44. /** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext<[string, ExternalRequests, string, string]>} ObjectSerializerContext */
  45. /** @import { InputFileSystem } from "../util/fs" */
  46. const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
  47. /** @typedef {string[]} ExternalRequests */
  48. class RemoteModule extends Module {
  49. /**
  50. * Creates an instance of RemoteModule.
  51. * @param {string} request request string
  52. * @param {ExternalRequests} externalRequests list of external requests to containers
  53. * @param {string} internalRequest name of exposed module in container
  54. * @param {string} shareScope the used share scope name
  55. */
  56. constructor(request, externalRequests, internalRequest, shareScope) {
  57. super(WEBPACK_MODULE_TYPE_REMOTE);
  58. /** @type {string} */
  59. this.request = request;
  60. /** @type {ExternalRequests} */
  61. this.externalRequests = externalRequests;
  62. /** @type {string} */
  63. this.internalRequest = internalRequest;
  64. /** @type {string} */
  65. this.shareScope = shareScope;
  66. /** @type {string} */
  67. this._identifier = `remote (${shareScope}) ${this.externalRequests.join(
  68. " "
  69. )} ${this.internalRequest}`;
  70. }
  71. /**
  72. * Returns the unique identifier used to reference this module.
  73. * @returns {string} a unique identifier of the module
  74. */
  75. identifier() {
  76. return this._identifier;
  77. }
  78. /**
  79. * Returns a human-readable identifier for this module.
  80. * @param {RequestShortener} requestShortener the request shortener
  81. * @returns {string} a user readable identifier of the module
  82. */
  83. readableIdentifier(requestShortener) {
  84. return `remote ${this.request}`;
  85. }
  86. /**
  87. * Gets the library identifier.
  88. * @param {LibIdentOptions} options options
  89. * @returns {LibIdent | null} an identifier for library inclusion
  90. */
  91. libIdent(options) {
  92. return `${this.layer ? `(${this.layer})/` : ""}webpack/container/remote/${
  93. this.request
  94. }`;
  95. }
  96. /**
  97. * Checks whether the module needs to be rebuilt for the current build state.
  98. * @param {NeedBuildContext} context context info
  99. * @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
  100. * @returns {void}
  101. */
  102. needBuild(context, callback) {
  103. callback(null, !this.buildInfo);
  104. }
  105. /**
  106. * Builds the module using the provided compilation context.
  107. * @param {WebpackOptions} options webpack options
  108. * @param {Compilation} compilation the compilation
  109. * @param {ResolverWithOptions} resolver the resolver
  110. * @param {InputFileSystem} fs the file system
  111. * @param {BuildCallback} callback callback function
  112. * @returns {void}
  113. */
  114. build(options, compilation, resolver, fs, callback) {
  115. this.buildMeta = {};
  116. this.buildInfo = {
  117. strict: true
  118. };
  119. this.clearDependenciesAndBlocks();
  120. if (this.externalRequests.length === 1) {
  121. this.addDependency(
  122. new RemoteToExternalDependency(this.externalRequests[0])
  123. );
  124. } else {
  125. this.addDependency(new FallbackDependency(this.externalRequests));
  126. }
  127. callback();
  128. }
  129. /**
  130. * Returns the estimated size for the requested source type.
  131. * @param {string=} type the source type for which the size should be estimated
  132. * @returns {number} the estimated size of the module (must be non-zero)
  133. */
  134. size(type) {
  135. return 6;
  136. }
  137. /**
  138. * Returns the source types this module can generate.
  139. * @returns {SourceTypes} types available (do not mutate)
  140. */
  141. getSourceTypes() {
  142. return REMOTE_AND_SHARE_INIT_TYPES;
  143. }
  144. /**
  145. * Basic source types are high-level categories like javascript, css, webassembly, etc.
  146. * We only have built-in knowledge about the javascript basic type here; other basic types may be
  147. * added or changed over time by generators and do not need to be handled or detected here.
  148. *
  149. * Some modules, e.g. RemoteModule, may return non-basic source types like "remote" and "share-init"
  150. * from getSourceTypes(), but their generated output is still JavaScript, i.e. their basic type is JS.
  151. * @returns {BasicSourceTypes} types available (do not mutate)
  152. */
  153. getSourceBasicTypes() {
  154. return JAVASCRIPT_TYPES;
  155. }
  156. /**
  157. * Returns export type.
  158. * @param {ModuleGraph} moduleGraph the module graph
  159. * @param {boolean | undefined} strict the importing module is strict
  160. * @returns {ExportsType} export type
  161. * "namespace": Exports is already a namespace object. namespace = exports.
  162. * "dynamic": Check at runtime if __esModule is set. When set: namespace = { ...exports, default: exports }. When not set: namespace = { default: exports }.
  163. * "default-only": Provide a namespace object with only default export. namespace = { default: exports }
  164. * "default-with-named": Provide a namespace object with named and default export. namespace = { ...exports, default: exports }
  165. */
  166. getExportsType(moduleGraph, strict) {
  167. return "dynamic";
  168. }
  169. /**
  170. * Returns the path used when matching this module against rule conditions.
  171. * @returns {NameForCondition | null} absolute path which should be used for condition matching (usually the resource path)
  172. */
  173. nameForCondition() {
  174. return this.request;
  175. }
  176. /**
  177. * Generates code and runtime requirements for this module.
  178. * @param {CodeGenerationContext} context context for code generation
  179. * @returns {CodeGenerationResult} result
  180. */
  181. codeGeneration({ moduleGraph, chunkGraph }) {
  182. const module = moduleGraph.getModule(this.dependencies[0]);
  183. const id = module && chunkGraph.getModuleId(module);
  184. /** @type {Sources} */
  185. const sources = new Map();
  186. sources.set("remote", new RawSource(""));
  187. /** @type {CodeGenerationResultData} */
  188. const data = new Map();
  189. data.set("share-init", [
  190. {
  191. shareScope: this.shareScope,
  192. initStage: 20,
  193. init: id === undefined ? "" : `initExternal(${JSON.stringify(id)});`
  194. }
  195. ]);
  196. return { sources, data, runtimeRequirements: RUNTIME_REQUIREMENTS };
  197. }
  198. /**
  199. * Serializes this instance into the provided serializer context.
  200. * @param {ObjectSerializerContext} context context
  201. */
  202. serialize(context) {
  203. context
  204. .write(this.request)
  205. .write(this.externalRequests)
  206. .write(this.internalRequest)
  207. .write(this.shareScope);
  208. super.serialize(context);
  209. }
  210. /**
  211. * Restores this instance from the provided deserializer context.
  212. * @param {ObjectDeserializerContext} context context
  213. * @returns {RemoteModule} deserialized module
  214. */
  215. static deserialize(context) {
  216. const request = context.read();
  217. const c1 = context.rest;
  218. const externalRequests = c1.read();
  219. const c2 = c1.rest;
  220. const internalRequest = c2.read();
  221. const c3 = c2.rest;
  222. const obj = new RemoteModule(
  223. request,
  224. externalRequests,
  225. internalRequest,
  226. c3.read()
  227. );
  228. obj.deserialize(c3.rest);
  229. return obj;
  230. }
  231. }
  232. makeSerializable(RemoteModule, "webpack/lib/container/RemoteModule");
  233. module.exports = RemoteModule;