UNPKG

react-dynamic-remote-component

Version:

Allows you to dynamically load a component from a remote using webpack 5's module federation.

210 lines (180 loc) 6.31 kB
import _objectSpread from '@babel/runtime/helpers/objectSpread2'; import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties'; import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator'; import _regeneratorRuntime from '@babel/runtime/regenerator'; import { jsx } from 'react/jsx-runtime'; var getRemoteModuleId = function getRemoteModuleId(_ref) { var url = _ref.url, module = _ref.module, scope = _ref.scope; return [url, scope, module].join(); }; var attachScript = function attachScript(remoteModule) { var id = getRemoteModuleId(remoteModule); var existingElement = document.getElementById(id); if (existingElement) { //@ts-expect-error if (window[remoteModule.scope]) return Promise.resolve(true);else return new Promise(function (resolve) { existingElement.onload = function (e) { resolve(true); }; }); } var element = document.createElement("script"); element.src = remoteModule.url; element.type = "text/javascript"; element.async = true; element.id = id; var scriptLoadPromise = new Promise(function (resolve, reject) { element.onload = function () { return resolve(element); }; element.onerror = function (e) { reject(e); }; }); document.head.appendChild(element); return scriptLoadPromise; }; /* eslint-disable no-unreachable */ var loadModule = function loadModule(url, scope, module) { return /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var container, factory, Module, error; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return __webpack_init_sharing__("default"); case 3: //@ts-expect-error container = window[scope]; if (container.isInitialized) { _context.next = 8; break; } container.isInitialized = true; //@ts-expect-error _context.next = 8; return container.init(__webpack_share_scopes__.default); case 8: _context.next = 10; return window[scope].get(module); case 10: factory = _context.sent; Module = factory(); return _context.abrupt("return", Module); case 15: _context.prev = 15; _context.t0 = _context["catch"](0); error = new Error("There was a problem loading the remote module. Please check the parameters (url: ".concat(url, " scope: ").concat(scope, " module: ").concat(module, ")")); error.name = "RemoteModuleLoadingError"; throw error; case 20: case "end": return _context.stop(); } } }, _callee, null, [[0, 15]]); })); }; var suspend = function suspend(promise) { var result; var status = "pending"; var suspender = promise.then(function (response) { status = "success"; result = response; }, function (error) { status = "error"; result = error; }); return function () { switch (status) { case "pending": { throw suspender; } case "error": { throw result; } default: { return result; } } }; }; var _excluded = ["unLoadScriptOnUnmount", "exportName", "url", "scope", "module"]; var getModule = function getModule(remoteModule) { window.remoteModuleDictionary = window.remoteModuleDictionary || {}; var id = getRemoteModuleId(remoteModule); var existingModule = window.remoteModuleDictionary[id]; if (existingModule) return existingModule;else { window.remoteModuleDictionary[id] = new Promise( /*#__PURE__*/function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(resolve, reject) { var _module; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return attachScript(remoteModule); case 3: _context.next = 5; return loadModule(remoteModule.url, remoteModule.scope, remoteModule.module)(); case 5: _module = _context.sent; resolve(_module); _context.next = 12; break; case 9: _context.prev = 9; _context.t0 = _context["catch"](0); reject(_context.t0); case 12: case "end": return _context.stop(); } } }, _callee, null, [[0, 9]]); })); return function (_x, _x2) { return _ref.apply(this, arguments); }; }()); return window.remoteModuleDictionary[id]; } }; var getModuleSuspended = function getModuleSuspended(remoteModule) { window.remoteObjectDictionary = window.remoteObjectDictionary || {}; var id = getRemoteModuleId(remoteModule); var existingCaller = window.remoteObjectDictionary[id]; if (existingCaller) return existingCaller();else { var caller = suspend(getModule(remoteModule)); window.remoteObjectDictionary[id] = caller; return caller(); } }; var useRemoteModule = function useRemoteModule(remoteModule) { return getModuleSuspended(remoteModule); }; function RemoteComponent(props) { props.unLoadScriptOnUnmount; var _props$exportName = props.exportName, exportName = _props$exportName === void 0 ? "default" : _props$exportName, url = props.url, scope = props.scope, module = props.module, componentProps = _objectWithoutProperties(props, _excluded); var _getModuleSuspended = getModuleSuspended({ url: url, scope: scope, module: module }), Component = _getModuleSuspended[exportName]; return /*#__PURE__*/jsx(Component, _objectSpread({}, componentProps)); } export { RemoteComponent, getModule, useRemoteModule }; //# sourceMappingURL=index.js.map