"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.frameworkConfiguration = void 0; exports.loadMicroApp = loadMicroApp; exports.registerMicroApps = registerMicroApps; exports.start = start; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _noop2 = _interopRequireDefault(require("lodash/noop")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _tslib = require("tslib"); var _singleSpa = require("single-spa"); var _loader = require("./loader"); var _prefetch = require("./prefetch"); var _utils = require("./utils"); var microApps = []; var frameworkConfiguration = {}; exports.frameworkConfiguration = frameworkConfiguration; var started = false; var defaultUrlRerouteOnly = true; var frameworkStartedDefer = new _utils.Deferred(); var autoDowngradeForLowVersionBrowser = function autoDowngradeForLowVersionBrowser(configuration) { var sandbox = configuration.sandbox, singular = configuration.singular; if (sandbox) { if (!window.Proxy) { console.warn('[qiankun] Miss window.Proxy, proxySandbox will degenerate into snapshotSandbox'); if (singular === false) { console.warn('[qiankun] Setting singular as false may cause unexpected behavior while your browser not support window.Proxy'); } return Object.assign(Object.assign({}, configuration), { sandbox: (0, _typeof2.default)(sandbox) === 'object' ? Object.assign(Object.assign({}, sandbox), { loose: true }) : { loose: true } }); } } return configuration; }; function registerMicroApps(apps, lifeCycles) { var _this = this; // Each app only needs to be registered once var unregisteredApps = apps.filter(function (app) { return !microApps.some(function (registeredApp) { return registeredApp.name === app.name; }); }); microApps = [].concat((0, _toConsumableArray2.default)(microApps), (0, _toConsumableArray2.default)(unregisteredApps)); unregisteredApps.forEach(function (app) { var name = app.name, activeRule = app.activeRule, _app$loader = app.loader, loader = _app$loader === void 0 ? _noop2.default : _app$loader, props = app.props, appConfig = (0, _tslib.__rest)(app, ["name", "activeRule", "loader", "props"]); (0, _singleSpa.registerApplication)({ name: name, app: function app() { return (0, _tslib.__awaiter)(_this, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee3() { var _this2 = this; var _a, mount, otherMicroAppConfigs; return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: loader(true); _context3.next = 3; return frameworkStartedDefer.promise; case 3: _context3.next = 5; return (0, _loader.loadApp)(Object.assign({ name: name, props: props }, appConfig), frameworkConfiguration, lifeCycles); case 5: _context3.t0 = _context3.sent; _a = (0, _context3.t0)(); mount = _a.mount; otherMicroAppConfigs = (0, _tslib.__rest)(_a, ["mount"]); return _context3.abrupt("return", Object.assign({ mount: [function () { return (0, _tslib.__awaiter)(_this2, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee() { return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", loader(true)); case 1: case "end": return _context.stop(); } } }, _callee); })); }].concat((0, _toConsumableArray2.default)((0, _utils.toArray)(mount)), [function () { return (0, _tslib.__awaiter)(_this2, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee2() { return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: return _context2.abrupt("return", loader(false)); case 1: case "end": return _context2.stop(); } } }, _callee2); })); }]) }, otherMicroAppConfigs)); case 10: case "end": return _context3.stop(); } } }, _callee3); })); }, activeWhen: activeRule, customProps: props }); }); } var appConfigPromiseGetterMap = new Map(); var containerMicroAppsMap = new Map(); function loadMicroApp(app, configuration, lifeCycles) { var _this3 = this; var _a; var props = app.props, name = app.name; var container = 'container' in app ? app.container : undefined; // Must compute the container xpath at beginning to keep it consist around app running // If we compute it every time, the container dom structure most probably been changed and result in a different xpath value var containerXPath = (0, _utils.getContainerXPath)(container); var appContainerXPathKey = "".concat(name, "-").concat(containerXPath); var microApp; var wrapParcelConfigForRemount = function wrapParcelConfigForRemount(config) { var microAppConfig = config; if (container) { if (containerXPath) { var containerMicroApps = containerMicroAppsMap.get(appContainerXPathKey); if (containerMicroApps === null || containerMicroApps === void 0 ? void 0 : containerMicroApps.length) { var mount = [function () { return (0, _tslib.__awaiter)(_this3, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee4() { var prevLoadMicroApps, prevLoadMicroAppsWhichNotBroken; return _regenerator.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: // While there are multiple micro apps mounted on the same container, we must wait until the prev instances all had unmounted // Otherwise it will lead some concurrent issues prevLoadMicroApps = containerMicroApps.slice(0, containerMicroApps.indexOf(microApp)); prevLoadMicroAppsWhichNotBroken = prevLoadMicroApps.filter(function (v) { return v.getStatus() !== 'LOAD_ERROR' && v.getStatus() !== 'SKIP_BECAUSE_BROKEN'; }); _context4.next = 4; return Promise.all(prevLoadMicroAppsWhichNotBroken.map(function (v) { return v.unmountPromise; })); case 4: case "end": return _context4.stop(); } } }, _callee4); })); }].concat((0, _toConsumableArray2.default)((0, _utils.toArray)(microAppConfig.mount))); microAppConfig = Object.assign(Object.assign({}, config), { mount: mount }); } } } return Object.assign(Object.assign({}, microAppConfig), { // empty bootstrap hook which should not run twice while it calling from cached micro app bootstrap: function bootstrap() { return Promise.resolve(); } }); }; /** * using name + container xpath as the micro app instance id, * it means if you rendering a micro app to a dom which have been rendered before, * the micro app would not load and evaluate its lifecycles again */ var memorizedLoadingFn = function memorizedLoadingFn() { return (0, _tslib.__awaiter)(_this3, void 0, void 0, /*#__PURE__*/_regenerator.default.mark(function _callee5() { var userConfiguration, $$cacheLifecycleByAppName, parcelConfigGetterPromise, _parcelConfigGetterPromise, parcelConfigObjectGetterPromise; return _regenerator.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: userConfiguration = autoDowngradeForLowVersionBrowser(configuration !== null && configuration !== void 0 ? configuration : Object.assign(Object.assign({}, frameworkConfiguration), { singular: false })); $$cacheLifecycleByAppName = userConfiguration.$$cacheLifecycleByAppName; if (!container) { _context5.next = 21; break; } if (!$$cacheLifecycleByAppName) { _context5.next = 12; break; } parcelConfigGetterPromise = appConfigPromiseGetterMap.get(name); if (!parcelConfigGetterPromise) { _context5.next = 12; break; } _context5.t0 = wrapParcelConfigForRemount; _context5.next = 9; return parcelConfigGetterPromise; case 9: _context5.t1 = _context5.sent; _context5.t2 = (0, _context5.t1)(container); return _context5.abrupt("return", (0, _context5.t0)(_context5.t2)); case 12: if (!containerXPath) { _context5.next = 21; break; } _parcelConfigGetterPromise = appConfigPromiseGetterMap.get(appContainerXPathKey); if (!_parcelConfigGetterPromise) { _context5.next = 21; break; } _context5.t3 = wrapParcelConfigForRemount; _context5.next = 18; return _parcelConfigGetterPromise; case 18: _context5.t4 = _context5.sent; _context5.t5 = (0, _context5.t4)(container); return _context5.abrupt("return", (0, _context5.t3)(_context5.t5)); case 21: parcelConfigObjectGetterPromise = (0, _loader.loadApp)(app, userConfiguration, lifeCycles); if (container) { if ($$cacheLifecycleByAppName) { appConfigPromiseGetterMap.set(name, parcelConfigObjectGetterPromise); } else if (containerXPath) appConfigPromiseGetterMap.set(appContainerXPathKey, parcelConfigObjectGetterPromise); } _context5.next = 25; return parcelConfigObjectGetterPromise; case 25: _context5.t6 = _context5.sent; return _context5.abrupt("return", (0, _context5.t6)(container)); case 27: case "end": return _context5.stop(); } } }, _callee5); })); }; if (!started && (configuration === null || configuration === void 0 ? void 0 : configuration.autoStart) !== false) { // We need to invoke start method of single-spa as the popstate event should be dispatched while the main app calling pushState/replaceState automatically, // but in single-spa it will check the start status before it dispatch popstate // see https://github.com/single-spa/single-spa/blob/f28b5963be1484583a072c8145ac0b5a28d91235/src/navigation/navigation-events.js#L101 // ref https://github.com/umijs/qiankun/pull/1071 (0, _singleSpa.start)({ urlRerouteOnly: (_a = frameworkConfiguration.urlRerouteOnly) !== null && _a !== void 0 ? _a : defaultUrlRerouteOnly }); } microApp = (0, _singleSpa.mountRootParcel)(memorizedLoadingFn, Object.assign({ domElement: document.createElement('div') }, props)); if (container) { if (containerXPath) { // Store the microApps which they mounted on the same container var microAppsRef = containerMicroAppsMap.get(appContainerXPathKey) || []; microAppsRef.push(microApp); containerMicroAppsMap.set(appContainerXPathKey, microAppsRef); var cleanup = function cleanup() { var index = microAppsRef.indexOf(microApp); microAppsRef.splice(index, 1); // @ts-ignore microApp = null; }; // gc after unmount microApp.unmountPromise.then(cleanup).catch(cleanup); } } return microApp; } function start() { var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; exports.frameworkConfiguration = frameworkConfiguration = Object.assign({ prefetch: true, singular: true, sandbox: true }, opts); var _frameworkConfigurati = frameworkConfiguration, prefetch = _frameworkConfigurati.prefetch, sandbox = _frameworkConfigurati.sandbox, singular = _frameworkConfigurati.singular, _frameworkConfigurati2 = _frameworkConfigurati.urlRerouteOnly, urlRerouteOnly = _frameworkConfigurati2 === void 0 ? defaultUrlRerouteOnly : _frameworkConfigurati2, importEntryOpts = (0, _tslib.__rest)(frameworkConfiguration, ["prefetch", "sandbox", "singular", "urlRerouteOnly"]); if (prefetch) { (0, _prefetch.doPrefetchStrategy)(microApps, prefetch, importEntryOpts); } exports.frameworkConfiguration = frameworkConfiguration = autoDowngradeForLowVersionBrowser(frameworkConfiguration); (0, _singleSpa.start)({ urlRerouteOnly: urlRerouteOnly }); started = true; frameworkStartedDefer.resolve(); }