ttk-mf-react
Advanced tools
| import React, { ReactElement } from "react"; | ||
| import ReactDOM from "react-dom"; | ||
| import { Map } from 'immutable'; | ||
| export type LifecycleProps = { | ||
| packageName: string, | ||
| targetDomId: string, | ||
| container: HTMLElement, | ||
| startAppName: string, | ||
| params: Record<string, any>, | ||
| callbacks: Record<string, any>, | ||
| onSaveState: (state: any) => void, | ||
| restoreState: any, | ||
| render: (props: any) => ReactElement, | ||
| state: Map<string, any>, | ||
| } | ||
| /** | ||
| * single-SPA生命周期钩子,只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 | ||
| * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 | ||
| */ | ||
| export const bootstrap = (props: LifecycleProps) => { | ||
| const { packageName, startAppName } = props; | ||
| console.log(`[${packageName}] app bootstraped. startAppName:`, startAppName); | ||
| } | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 | ||
| */ | ||
| export const mount = (props: LifecycleProps) => { | ||
| const { packageName, targetDomId, container, startAppName, restoreState, params, callbacks, render: Root } = props; | ||
| console.log(`[${packageName}] app mounted. startAppName:`, startAppName); | ||
| ReactDOM.render( | ||
| <Root startAppName={startAppName} initData={restoreState} params={params} callbacks={callbacks} />, | ||
| container ? container.querySelector(`#${targetDomId}`) : document.getElementById(targetDomId), | ||
| ); | ||
| } | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 | ||
| */ | ||
| export const unmount = (props: LifecycleProps) => { | ||
| const { packageName, targetDomId, container, startAppName, onSaveState, state } = props; | ||
| console.log(`[${packageName}] app unmount. startAppName:`, startAppName); | ||
| if (startAppName && state && onSaveState) { | ||
| state.get(startAppName).filter((value: any, key: string) => key.startsWith('AppLoader')) | ||
| .take(1) | ||
| .forEach((value: any) => { | ||
| onSaveState(value.get('data').toJS()); | ||
| }) | ||
| } | ||
| const element = container ? container.querySelector(`#${targetDomId}`) : document.getElementById(targetDomId); | ||
| element && ReactDOM.unmountComponentAtNode(element); | ||
| } | ||
| /** | ||
| * single-SPA可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 | ||
| */ | ||
| export const update = (props: LifecycleProps) => { | ||
| const { packageName, targetDomId, container, startAppName, restoreState, params, callbacks, render: Update } = props; | ||
| console.log(`[${packageName}] app update. startAppName:`, startAppName); | ||
| const element = container?.firstElementChild?.querySelector(`#${targetDomId}`) || document.getElementById(targetDomId); | ||
| ReactDOM.render( | ||
| <Update startAppName={startAppName} initData={restoreState} params={params} callbacks={callbacks} />, | ||
| element | ||
| ); | ||
| } |
+168
-41
| (function (global, factory) { | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('qiankun')) : | ||
| typeof define === 'function' && define.amd ? define(['exports', 'react', 'qiankun'], factory) : | ||
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ttk_mf_react = {}, global.react, global.qiankun)); | ||
| }(this, (function (exports, React, qiankun) { 'use strict'; | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('qiankun'), require('react-dom')) : | ||
| typeof define === 'function' && define.amd ? define(['exports', 'react', 'qiankun', 'react-dom'], factory) : | ||
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ttk_mf_react = {}, global.react, global.qiankun, global.ReactDOM)); | ||
| }(this, (function (exports, React, qiankun, ReactDOM) { 'use strict'; | ||
@@ -10,15 +10,45 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
| var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
| var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM); | ||
| var STYLE_APP = { | ||
| width: '100%', | ||
| height: '100%', | ||
| overflow: 'hidden' | ||
| }; | ||
| var STYLE_APP_CONTAINER = { | ||
| width: '100%', | ||
| height: '100%' | ||
| }; | ||
| var STYLE_APP_SPIN = { | ||
| width: '100%', | ||
| height: '100%', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center' | ||
| }; | ||
| var STYLE_APP_ERROR = { | ||
| width: '100%', | ||
| height: '100%', | ||
| padding: 10, | ||
| color: 'red' | ||
| }; | ||
| var STYLE_APP_ERROR_MSG = { | ||
| display: 'block', | ||
| fontSize: 16 | ||
| }; | ||
| function mfApp(props) { | ||
| var microApp = props.microApp; | ||
| var name = microApp.name, | ||
| entry = microApp.entry, | ||
| params = microApp.params, | ||
| onSaveState = microApp.onSaveState, | ||
| restoreState = microApp.restoreState, | ||
| startAppName = microApp.startAppName, | ||
| _microApp$singular = microApp.singular, | ||
| singular = _microApp$singular === void 0 ? true : _microApp$singular, | ||
| Loading = microApp.renderLoading, | ||
| Error = microApp.renderError; | ||
| var mfAppConfig = props.mfAppConfig; | ||
| var name = mfAppConfig.name, | ||
| entry = mfAppConfig.entry, | ||
| startAppName = mfAppConfig.startAppName, | ||
| _mfAppConfig$delayLoa = mfAppConfig.delayLoading, | ||
| delayLoading = _mfAppConfig$delayLoa === void 0 ? false : _mfAppConfig$delayLoa, | ||
| params = mfAppConfig.params, | ||
| callbacks = mfAppConfig.callbacks, | ||
| onSaveState = mfAppConfig.onSaveState, | ||
| restoreState = mfAppConfig.restoreState, | ||
| _mfAppConfig$singular = mfAppConfig.singular, | ||
| singular = _mfAppConfig$singular === void 0 ? true : _mfAppConfig$singular, | ||
| RenderLoading = mfAppConfig.renderLoading, | ||
| RenderError = mfAppConfig.renderError; | ||
@@ -33,3 +63,3 @@ var _useState = React.useState(true), | ||
| var _useState3 = React.useState("\u5FAE\u5E94\u7528" + microApp.name + "\u52A0\u8F7D\u5931\u8D25"), | ||
| var _useState3 = React.useState("\u5FAE\u5E94\u7528" + name + "\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\uFF01"), | ||
| errorMsg = _useState3[0]; | ||
@@ -39,9 +69,5 @@ | ||
| errorDesc = _useState4[0], | ||
| setErrorDesc = _useState4[1]; // let [app, setApp]: [MicroApp | null, Dispatch<SetStateAction<null>>] = useState(null) | ||
| setErrorDesc = _useState4[1]; | ||
| var _useState5 = React.useState(null), | ||
| app = _useState5[0], | ||
| setApp = _useState5[1]; | ||
| var appRef = React.useRef(null); | ||
| var ref = React.useRef(null); | ||
@@ -61,2 +87,6 @@ var errorHandler = React.useCallback(function (event) { | ||
| if (delayLoading) { | ||
| return; | ||
| } | ||
| qiankun.addGlobalUncaughtErrorHandler(errorHandler); | ||
@@ -70,4 +100,4 @@ var configuration = { | ||
| if (!app) { | ||
| app = qiankun.loadMicroApp({ | ||
| if (!appRef.current) { | ||
| appRef.current = qiankun.loadMicroApp({ | ||
| name: name, | ||
@@ -80,11 +110,11 @@ entry: entry, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| } | ||
| }, configuration); | ||
| app.mountPromise.then(function () { | ||
| appRef.current.mountPromise.then(function () { | ||
| setLoading(false); | ||
| }); | ||
| setApp(app); | ||
| } else if (app.update) { | ||
| app.update({ | ||
| } else if (appRef.current.update) { | ||
| appRef.current.update({ | ||
| container: ref.current, | ||
@@ -94,3 +124,4 @@ restoreState: restoreState, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| }); | ||
@@ -100,6 +131,10 @@ } | ||
| return function () { | ||
| var _app; | ||
| var _appRef$current; | ||
| if (((_app = app) == null ? void 0 : _app.getStatus()) === 'MOUNTED') { | ||
| app.unmount(); | ||
| var status = (_appRef$current = appRef.current) == null ? void 0 : _appRef$current.getStatus(); | ||
| if ('MOUNTED' === status) { | ||
| var _appRef$current2; | ||
| (_appRef$current2 = appRef.current) == null ? void 0 : _appRef$current2.unmount(); | ||
| } | ||
@@ -109,14 +144,18 @@ | ||
| }; | ||
| }, [microApp]); | ||
| }, [mfAppConfig, delayLoading]); | ||
| return /*#__PURE__*/React__default['default'].createElement("div", { | ||
| className: "ttk-mf-app" | ||
| }, loading ? /*#__PURE__*/React__default['default'].createElement(Loading, { | ||
| className: "ttk-mf-app-spin", | ||
| style: STYLE_APP | ||
| }, (delayLoading || loading) && RenderLoading ? /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_SPIN | ||
| }, /*#__PURE__*/React__default['default'].createElement(RenderLoading, { | ||
| loading: loading | ||
| }) : null, error ? /*#__PURE__*/React__default['default'].createElement(Error, { | ||
| className: "ttk-mf-app-alert", | ||
| })) : null, error ? /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_ERROR | ||
| }, RenderError ? /*#__PURE__*/React__default['default'].createElement(RenderError, { | ||
| message: errorMsg, | ||
| description: errorDesc | ||
| }) : null, /*#__PURE__*/React__default['default'].createElement("div", { | ||
| className: "ttk-mf-app-container", | ||
| }) : [/*#__PURE__*/React__default['default'].createElement("span", { | ||
| style: STYLE_APP_ERROR_MSG | ||
| }, errorMsg), /*#__PURE__*/React__default['default'].createElement("span", null, errorDesc)]) : null, /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_CONTAINER, | ||
| ref: ref | ||
@@ -126,2 +165,90 @@ })); | ||
| /** | ||
| * single-SPA生命周期钩子,只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 | ||
| * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 | ||
| */ | ||
| var bootstrap = function bootstrap(props) { | ||
| var packageName = props.packageName, | ||
| startAppName = props.startAppName; | ||
| console.log("[" + packageName + "] app bootstraped. startAppName:", startAppName); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 | ||
| */ | ||
| var mount = function mount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Root = props.render; | ||
| console.log("[" + packageName + "] app mounted. startAppName:", startAppName); | ||
| ReactDOM__default['default'].render( /*#__PURE__*/React__default['default'].createElement(Root, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId)); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 | ||
| */ | ||
| var unmount = function unmount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| onSaveState = props.onSaveState, | ||
| state = props.state; | ||
| console.log("[" + packageName + "] app unmount. startAppName:", startAppName); | ||
| if (startAppName && state && onSaveState) { | ||
| state.get(startAppName).filter(function (value, key) { | ||
| return key.startsWith('AppLoader'); | ||
| }).take(1).forEach(function (value) { | ||
| onSaveState(value.get('data').toJS()); | ||
| }); | ||
| } | ||
| var element = container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId); | ||
| element && ReactDOM__default['default'].unmountComponentAtNode(element); | ||
| }; | ||
| /** | ||
| * single-SPA可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 | ||
| */ | ||
| var update = function update(props) { | ||
| var _container$firstEleme; | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Update = props.render; | ||
| console.log("[" + packageName + "] app update. startAppName:", startAppName); | ||
| var element = (container == null ? void 0 : (_container$firstEleme = container.firstElementChild) == null ? void 0 : _container$firstEleme.querySelector("#" + targetDomId)) || document.getElementById(targetDomId); | ||
| ReactDOM__default['default'].render( /*#__PURE__*/React__default['default'].createElement(Update, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), element); | ||
| }; | ||
| var lifecycle = /*#__PURE__*/Object.freeze({ | ||
| __proto__: null, | ||
| bootstrap: bootstrap, | ||
| mount: mount, | ||
| unmount: unmount, | ||
| update: update | ||
| }); | ||
| exports.lifecycle = lifecycle; | ||
| exports.mfApp = mfApp; | ||
@@ -128,0 +255,0 @@ |
+164
-38
| import React, { useState, useRef, useCallback, useEffect } from 'react'; | ||
| import { addGlobalUncaughtErrorHandler, loadMicroApp, removeGlobalUncaughtErrorHandler } from 'qiankun'; | ||
| import ReactDOM from 'react-dom'; | ||
| var STYLE_APP = { | ||
| width: '100%', | ||
| height: '100%', | ||
| overflow: 'hidden' | ||
| }; | ||
| var STYLE_APP_CONTAINER = { | ||
| width: '100%', | ||
| height: '100%' | ||
| }; | ||
| var STYLE_APP_SPIN = { | ||
| width: '100%', | ||
| height: '100%', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center' | ||
| }; | ||
| var STYLE_APP_ERROR = { | ||
| width: '100%', | ||
| height: '100%', | ||
| padding: 10, | ||
| color: 'red' | ||
| }; | ||
| var STYLE_APP_ERROR_MSG = { | ||
| display: 'block', | ||
| fontSize: 16 | ||
| }; | ||
| function mfApp(props) { | ||
| var microApp = props.microApp; | ||
| var name = microApp.name, | ||
| entry = microApp.entry, | ||
| params = microApp.params, | ||
| onSaveState = microApp.onSaveState, | ||
| restoreState = microApp.restoreState, | ||
| startAppName = microApp.startAppName, | ||
| _microApp$singular = microApp.singular, | ||
| singular = _microApp$singular === void 0 ? true : _microApp$singular, | ||
| Loading = microApp.renderLoading, | ||
| Error = microApp.renderError; | ||
| var mfAppConfig = props.mfAppConfig; | ||
| var name = mfAppConfig.name, | ||
| entry = mfAppConfig.entry, | ||
| startAppName = mfAppConfig.startAppName, | ||
| _mfAppConfig$delayLoa = mfAppConfig.delayLoading, | ||
| delayLoading = _mfAppConfig$delayLoa === void 0 ? false : _mfAppConfig$delayLoa, | ||
| params = mfAppConfig.params, | ||
| callbacks = mfAppConfig.callbacks, | ||
| onSaveState = mfAppConfig.onSaveState, | ||
| restoreState = mfAppConfig.restoreState, | ||
| _mfAppConfig$singular = mfAppConfig.singular, | ||
| singular = _mfAppConfig$singular === void 0 ? true : _mfAppConfig$singular, | ||
| RenderLoading = mfAppConfig.renderLoading, | ||
| RenderError = mfAppConfig.renderError; | ||
@@ -25,3 +55,3 @@ var _useState = useState(true), | ||
| var _useState3 = useState("\u5FAE\u5E94\u7528" + microApp.name + "\u52A0\u8F7D\u5931\u8D25"), | ||
| var _useState3 = useState("\u5FAE\u5E94\u7528" + name + "\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\uFF01"), | ||
| errorMsg = _useState3[0]; | ||
@@ -31,9 +61,5 @@ | ||
| errorDesc = _useState4[0], | ||
| setErrorDesc = _useState4[1]; // let [app, setApp]: [MicroApp | null, Dispatch<SetStateAction<null>>] = useState(null) | ||
| setErrorDesc = _useState4[1]; | ||
| var _useState5 = useState(null), | ||
| app = _useState5[0], | ||
| setApp = _useState5[1]; | ||
| var appRef = useRef(null); | ||
| var ref = useRef(null); | ||
@@ -53,2 +79,6 @@ var errorHandler = useCallback(function (event) { | ||
| if (delayLoading) { | ||
| return; | ||
| } | ||
| addGlobalUncaughtErrorHandler(errorHandler); | ||
@@ -62,4 +92,4 @@ var configuration = { | ||
| if (!app) { | ||
| app = loadMicroApp({ | ||
| if (!appRef.current) { | ||
| appRef.current = loadMicroApp({ | ||
| name: name, | ||
@@ -72,11 +102,11 @@ entry: entry, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| } | ||
| }, configuration); | ||
| app.mountPromise.then(function () { | ||
| appRef.current.mountPromise.then(function () { | ||
| setLoading(false); | ||
| }); | ||
| setApp(app); | ||
| } else if (app.update) { | ||
| app.update({ | ||
| } else if (appRef.current.update) { | ||
| appRef.current.update({ | ||
| container: ref.current, | ||
@@ -86,3 +116,4 @@ restoreState: restoreState, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| }); | ||
@@ -92,6 +123,10 @@ } | ||
| return function () { | ||
| var _app; | ||
| var _appRef$current; | ||
| if (((_app = app) == null ? void 0 : _app.getStatus()) === 'MOUNTED') { | ||
| app.unmount(); | ||
| var status = (_appRef$current = appRef.current) == null ? void 0 : _appRef$current.getStatus(); | ||
| if ('MOUNTED' === status) { | ||
| var _appRef$current2; | ||
| (_appRef$current2 = appRef.current) == null ? void 0 : _appRef$current2.unmount(); | ||
| } | ||
@@ -101,14 +136,18 @@ | ||
| }; | ||
| }, [microApp]); | ||
| }, [mfAppConfig, delayLoading]); | ||
| return /*#__PURE__*/React.createElement("div", { | ||
| className: "ttk-mf-app" | ||
| }, loading ? /*#__PURE__*/React.createElement(Loading, { | ||
| className: "ttk-mf-app-spin", | ||
| style: STYLE_APP | ||
| }, (delayLoading || loading) && RenderLoading ? /*#__PURE__*/React.createElement("div", { | ||
| style: STYLE_APP_SPIN | ||
| }, /*#__PURE__*/React.createElement(RenderLoading, { | ||
| loading: loading | ||
| }) : null, error ? /*#__PURE__*/React.createElement(Error, { | ||
| className: "ttk-mf-app-alert", | ||
| })) : null, error ? /*#__PURE__*/React.createElement("div", { | ||
| style: STYLE_APP_ERROR | ||
| }, RenderError ? /*#__PURE__*/React.createElement(RenderError, { | ||
| message: errorMsg, | ||
| description: errorDesc | ||
| }) : null, /*#__PURE__*/React.createElement("div", { | ||
| className: "ttk-mf-app-container", | ||
| }) : [/*#__PURE__*/React.createElement("span", { | ||
| style: STYLE_APP_ERROR_MSG | ||
| }, errorMsg), /*#__PURE__*/React.createElement("span", null, errorDesc)]) : null, /*#__PURE__*/React.createElement("div", { | ||
| style: STYLE_APP_CONTAINER, | ||
| ref: ref | ||
@@ -118,2 +157,89 @@ })); | ||
| export { mfApp }; | ||
| /** | ||
| * single-SPA生命周期钩子,只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 | ||
| * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 | ||
| */ | ||
| var bootstrap = function bootstrap(props) { | ||
| var packageName = props.packageName, | ||
| startAppName = props.startAppName; | ||
| console.log("[" + packageName + "] app bootstraped. startAppName:", startAppName); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 | ||
| */ | ||
| var mount = function mount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Root = props.render; | ||
| console.log("[" + packageName + "] app mounted. startAppName:", startAppName); | ||
| ReactDOM.render( /*#__PURE__*/React.createElement(Root, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId)); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 | ||
| */ | ||
| var unmount = function unmount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| onSaveState = props.onSaveState, | ||
| state = props.state; | ||
| console.log("[" + packageName + "] app unmount. startAppName:", startAppName); | ||
| if (startAppName && state && onSaveState) { | ||
| state.get(startAppName).filter(function (value, key) { | ||
| return key.startsWith('AppLoader'); | ||
| }).take(1).forEach(function (value) { | ||
| onSaveState(value.get('data').toJS()); | ||
| }); | ||
| } | ||
| var element = container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId); | ||
| element && ReactDOM.unmountComponentAtNode(element); | ||
| }; | ||
| /** | ||
| * single-SPA可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 | ||
| */ | ||
| var update = function update(props) { | ||
| var _container$firstEleme; | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Update = props.render; | ||
| console.log("[" + packageName + "] app update. startAppName:", startAppName); | ||
| var element = (container == null ? void 0 : (_container$firstEleme = container.firstElementChild) == null ? void 0 : _container$firstEleme.querySelector("#" + targetDomId)) || document.getElementById(targetDomId); | ||
| ReactDOM.render( /*#__PURE__*/React.createElement(Update, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), element); | ||
| }; | ||
| var lifecycle = /*#__PURE__*/Object.freeze({ | ||
| __proto__: null, | ||
| bootstrap: bootstrap, | ||
| mount: mount, | ||
| unmount: unmount, | ||
| update: update | ||
| }); | ||
| export { lifecycle, mfApp }; |
+165
-37
@@ -7,2 +7,3 @@ 'use strict'; | ||
| var qiankun = require('qiankun'); | ||
| var ReactDOM = require('react-dom'); | ||
@@ -12,15 +13,45 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
| var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
| var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM); | ||
| var STYLE_APP = { | ||
| width: '100%', | ||
| height: '100%', | ||
| overflow: 'hidden' | ||
| }; | ||
| var STYLE_APP_CONTAINER = { | ||
| width: '100%', | ||
| height: '100%' | ||
| }; | ||
| var STYLE_APP_SPIN = { | ||
| width: '100%', | ||
| height: '100%', | ||
| display: 'flex', | ||
| alignItems: 'center', | ||
| justifyContent: 'center' | ||
| }; | ||
| var STYLE_APP_ERROR = { | ||
| width: '100%', | ||
| height: '100%', | ||
| padding: 10, | ||
| color: 'red' | ||
| }; | ||
| var STYLE_APP_ERROR_MSG = { | ||
| display: 'block', | ||
| fontSize: 16 | ||
| }; | ||
| function mfApp(props) { | ||
| var microApp = props.microApp; | ||
| var name = microApp.name, | ||
| entry = microApp.entry, | ||
| params = microApp.params, | ||
| onSaveState = microApp.onSaveState, | ||
| restoreState = microApp.restoreState, | ||
| startAppName = microApp.startAppName, | ||
| _microApp$singular = microApp.singular, | ||
| singular = _microApp$singular === void 0 ? true : _microApp$singular, | ||
| Loading = microApp.renderLoading, | ||
| Error = microApp.renderError; | ||
| var mfAppConfig = props.mfAppConfig; | ||
| var name = mfAppConfig.name, | ||
| entry = mfAppConfig.entry, | ||
| startAppName = mfAppConfig.startAppName, | ||
| _mfAppConfig$delayLoa = mfAppConfig.delayLoading, | ||
| delayLoading = _mfAppConfig$delayLoa === void 0 ? false : _mfAppConfig$delayLoa, | ||
| params = mfAppConfig.params, | ||
| callbacks = mfAppConfig.callbacks, | ||
| onSaveState = mfAppConfig.onSaveState, | ||
| restoreState = mfAppConfig.restoreState, | ||
| _mfAppConfig$singular = mfAppConfig.singular, | ||
| singular = _mfAppConfig$singular === void 0 ? true : _mfAppConfig$singular, | ||
| RenderLoading = mfAppConfig.renderLoading, | ||
| RenderError = mfAppConfig.renderError; | ||
@@ -35,3 +66,3 @@ var _useState = React.useState(true), | ||
| var _useState3 = React.useState("\u5FAE\u5E94\u7528" + microApp.name + "\u52A0\u8F7D\u5931\u8D25"), | ||
| var _useState3 = React.useState("\u5FAE\u5E94\u7528" + name + "\u52A0\u8F7D\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D\uFF01"), | ||
| errorMsg = _useState3[0]; | ||
@@ -41,9 +72,5 @@ | ||
| errorDesc = _useState4[0], | ||
| setErrorDesc = _useState4[1]; // let [app, setApp]: [MicroApp | null, Dispatch<SetStateAction<null>>] = useState(null) | ||
| setErrorDesc = _useState4[1]; | ||
| var _useState5 = React.useState(null), | ||
| app = _useState5[0], | ||
| setApp = _useState5[1]; | ||
| var appRef = React.useRef(null); | ||
| var ref = React.useRef(null); | ||
@@ -63,2 +90,6 @@ var errorHandler = React.useCallback(function (event) { | ||
| if (delayLoading) { | ||
| return; | ||
| } | ||
| qiankun.addGlobalUncaughtErrorHandler(errorHandler); | ||
@@ -72,4 +103,4 @@ var configuration = { | ||
| if (!app) { | ||
| app = qiankun.loadMicroApp({ | ||
| if (!appRef.current) { | ||
| appRef.current = qiankun.loadMicroApp({ | ||
| name: name, | ||
@@ -82,11 +113,11 @@ entry: entry, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| } | ||
| }, configuration); | ||
| app.mountPromise.then(function () { | ||
| appRef.current.mountPromise.then(function () { | ||
| setLoading(false); | ||
| }); | ||
| setApp(app); | ||
| } else if (app.update) { | ||
| app.update({ | ||
| } else if (appRef.current.update) { | ||
| appRef.current.update({ | ||
| container: ref.current, | ||
@@ -96,3 +127,4 @@ restoreState: restoreState, | ||
| startAppName: startAppName, | ||
| params: params | ||
| params: params, | ||
| callbacks: callbacks | ||
| }); | ||
@@ -102,6 +134,10 @@ } | ||
| return function () { | ||
| var _app; | ||
| var _appRef$current; | ||
| if (((_app = app) == null ? void 0 : _app.getStatus()) === 'MOUNTED') { | ||
| app.unmount(); | ||
| var status = (_appRef$current = appRef.current) == null ? void 0 : _appRef$current.getStatus(); | ||
| if ('MOUNTED' === status) { | ||
| var _appRef$current2; | ||
| (_appRef$current2 = appRef.current) == null ? void 0 : _appRef$current2.unmount(); | ||
| } | ||
@@ -111,14 +147,18 @@ | ||
| }; | ||
| }, [microApp]); | ||
| }, [mfAppConfig, delayLoading]); | ||
| return /*#__PURE__*/React__default['default'].createElement("div", { | ||
| className: "ttk-mf-app" | ||
| }, loading ? /*#__PURE__*/React__default['default'].createElement(Loading, { | ||
| className: "ttk-mf-app-spin", | ||
| style: STYLE_APP | ||
| }, (delayLoading || loading) && RenderLoading ? /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_SPIN | ||
| }, /*#__PURE__*/React__default['default'].createElement(RenderLoading, { | ||
| loading: loading | ||
| }) : null, error ? /*#__PURE__*/React__default['default'].createElement(Error, { | ||
| className: "ttk-mf-app-alert", | ||
| })) : null, error ? /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_ERROR | ||
| }, RenderError ? /*#__PURE__*/React__default['default'].createElement(RenderError, { | ||
| message: errorMsg, | ||
| description: errorDesc | ||
| }) : null, /*#__PURE__*/React__default['default'].createElement("div", { | ||
| className: "ttk-mf-app-container", | ||
| }) : [/*#__PURE__*/React__default['default'].createElement("span", { | ||
| style: STYLE_APP_ERROR_MSG | ||
| }, errorMsg), /*#__PURE__*/React__default['default'].createElement("span", null, errorDesc)]) : null, /*#__PURE__*/React__default['default'].createElement("div", { | ||
| style: STYLE_APP_CONTAINER, | ||
| ref: ref | ||
@@ -128,2 +168,90 @@ })); | ||
| /** | ||
| * single-SPA生命周期钩子,只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。 | ||
| * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。 | ||
| */ | ||
| var bootstrap = function bootstrap(props) { | ||
| var packageName = props.packageName, | ||
| startAppName = props.startAppName; | ||
| console.log("[" + packageName + "] app bootstraped. startAppName:", startAppName); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法 | ||
| */ | ||
| var mount = function mount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Root = props.render; | ||
| console.log("[" + packageName + "] app mounted. startAppName:", startAppName); | ||
| ReactDOM__default['default'].render( /*#__PURE__*/React__default['default'].createElement(Root, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId)); | ||
| }; | ||
| /** | ||
| * single-SPA生命周期钩子,应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例 | ||
| */ | ||
| var unmount = function unmount(props) { | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| onSaveState = props.onSaveState, | ||
| state = props.state; | ||
| console.log("[" + packageName + "] app unmount. startAppName:", startAppName); | ||
| if (startAppName && state && onSaveState) { | ||
| state.get(startAppName).filter(function (value, key) { | ||
| return key.startsWith('AppLoader'); | ||
| }).take(1).forEach(function (value) { | ||
| onSaveState(value.get('data').toJS()); | ||
| }); | ||
| } | ||
| var element = container ? container.querySelector("#" + targetDomId) : document.getElementById(targetDomId); | ||
| element && ReactDOM__default['default'].unmountComponentAtNode(element); | ||
| }; | ||
| /** | ||
| * single-SPA可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效 | ||
| */ | ||
| var update = function update(props) { | ||
| var _container$firstEleme; | ||
| var packageName = props.packageName, | ||
| targetDomId = props.targetDomId, | ||
| container = props.container, | ||
| startAppName = props.startAppName, | ||
| restoreState = props.restoreState, | ||
| params = props.params, | ||
| callbacks = props.callbacks, | ||
| Update = props.render; | ||
| console.log("[" + packageName + "] app update. startAppName:", startAppName); | ||
| var element = (container == null ? void 0 : (_container$firstEleme = container.firstElementChild) == null ? void 0 : _container$firstEleme.querySelector("#" + targetDomId)) || document.getElementById(targetDomId); | ||
| ReactDOM__default['default'].render( /*#__PURE__*/React__default['default'].createElement(Update, { | ||
| startAppName: startAppName, | ||
| initData: restoreState, | ||
| params: params, | ||
| callbacks: callbacks | ||
| }), element); | ||
| }; | ||
| var lifecycle = /*#__PURE__*/Object.freeze({ | ||
| __proto__: null, | ||
| bootstrap: bootstrap, | ||
| mount: mount, | ||
| unmount: unmount, | ||
| update: update | ||
| }); | ||
| exports.lifecycle = lifecycle; | ||
| exports.mfApp = mfApp; |
+3
-5
| { | ||
| "name": "ttk-mf-react", | ||
| "version": "0.0.1", | ||
| "version": "0.0.2", | ||
| "description": "ttk微前端react", | ||
@@ -46,3 +46,2 @@ "main": "./lib/index.js", | ||
| "@rollup/plugin-commonjs": "^16.0.0", | ||
| "@rollup/plugin-json": "^4.1.0", | ||
| "@rollup/plugin-node-resolve": "^10.0.0", | ||
@@ -58,2 +57,3 @@ "@rollup/plugin-replace": "^2.3.4", | ||
| "gulp": "^4.0.2", | ||
| "immutable": "^4.0.0-rc.12", | ||
| "less": "^3.12.2", | ||
@@ -68,7 +68,5 @@ "less-plugin-npm-import": "^2.1.0", | ||
| "rollup-plugin-clear": "^2.0.7", | ||
| "rollup-plugin-less": "^1.1.3", | ||
| "typescript": "^4.1.2" | ||
| }, | ||
| "dependencies": { | ||
| "rollup-plugin-less": "^1.1.3" | ||
| } | ||
| } |
+2
-0
@@ -0,2 +1,4 @@ | ||
| 提供应用qiankun微前端的react组件及相关生命周期API给TTK工程使用的依赖库 | ||
| ## License | ||
@@ -3,0 +5,0 @@ |
+42
-29
@@ -1,9 +0,11 @@ | ||
| import React, { useState, useEffect, useRef, useCallback, Dispatch, SetStateAction } from 'react' | ||
| import React, { useState, useEffect, useRef, useCallback } from 'react' | ||
| import { MicroApp, loadMicroApp, addGlobalUncaughtErrorHandler, removeGlobalUncaughtErrorHandler } from 'qiankun'; | ||
| import './style.less'; | ||
| const STYLE_APP = { width: '100%', height: '100%', overflow: 'hidden' }; | ||
| const STYLE_APP_CONTAINER = { width: '100%', height: '100%' }; | ||
| const STYLE_APP_SPIN = { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' } | ||
| const STYLE_APP_ERROR = { width: '100%', height: '100%', padding: 10, color: 'red' }; | ||
| const STYLE_APP_ERROR_MSG = { display: 'block', fontSize: 16 }; | ||
| export type LoadingProps = { | ||
| loading: boolean; | ||
| className: string | ||
| loading: boolean | ||
| } | ||
@@ -13,13 +15,13 @@ export type ErrorProps = { | ||
| description: string, | ||
| className: string | ||
| } | ||
| export type MfAppConfig = { | ||
| name: string, | ||
| entry: string, | ||
| startAppName: string, | ||
| delayLoading: boolean, | ||
| params: any, | ||
| callbacks: any, | ||
| onSaveState: () => void, | ||
| restoreState: any, | ||
| startAppName: string, | ||
| singular: boolean, | ||
@@ -31,15 +33,14 @@ renderLoading: (props: LoadingProps) => JSX.Element, | ||
| export type MfAppProps = { | ||
| microApp: MfAppConfig | ||
| mfAppConfig: MfAppConfig | ||
| } | ||
| export function mfApp(props: MfAppProps) { | ||
| let microApp = props.microApp; | ||
| let { name, entry, params, onSaveState, restoreState, startAppName, singular = true, renderLoading: Loading, renderError: Error } = microApp; | ||
| let { mfAppConfig } = props; | ||
| let { name, entry, startAppName, delayLoading = false, params, callbacks, onSaveState, restoreState, singular = true, renderLoading: RenderLoading, renderError: RenderError } = mfAppConfig; | ||
| const [loading, setLoading] = useState(true); | ||
| const [error, setError] = useState(false); | ||
| const [errorMsg] = useState(`微应用${microApp.name}加载失败`); | ||
| const [errorMsg] = useState(`微应用${name}加载失败,请重新加载!`); | ||
| const [errorDesc, setErrorDesc] = useState(''); | ||
| // let [app, setApp]: [MicroApp | null, Dispatch<SetStateAction<null>>] = useState(null) | ||
| let [app, setApp]: [MicroApp | null, Dispatch<SetStateAction<MicroApp | null>>] = useState(null) | ||
| const appRef: React.MutableRefObject<MicroApp | null> = useRef(null); | ||
| const ref = useRef(null); | ||
@@ -60,2 +61,5 @@ | ||
| } | ||
| if (delayLoading) { | ||
| return; | ||
| } | ||
| addGlobalUncaughtErrorHandler(errorHandler); | ||
@@ -66,34 +70,43 @@ const configuration = { | ||
| } | ||
| if (!app) { | ||
| app = loadMicroApp({ | ||
| if (!appRef.current) { | ||
| appRef.current = loadMicroApp({ | ||
| name, | ||
| entry, | ||
| container: ref.current || '', | ||
| props: { restoreState, onSaveState, startAppName, params }, | ||
| props: { restoreState, onSaveState, startAppName, params, callbacks }, | ||
| }, configuration) | ||
| app.mountPromise.then(() => { | ||
| appRef.current.mountPromise.then(() => { | ||
| setLoading(false) | ||
| }) | ||
| setApp(app); | ||
| } else if (app.update) { | ||
| app.update({ | ||
| } else if (appRef.current.update) { | ||
| appRef.current.update({ | ||
| container: ref.current, | ||
| restoreState, onSaveState, startAppName, params | ||
| restoreState, onSaveState, startAppName, params, callbacks | ||
| }); | ||
| } | ||
| return () => { | ||
| if (app?.getStatus() === 'MOUNTED') { | ||
| app.unmount(); | ||
| const status = appRef.current?.getStatus(); | ||
| if ('MOUNTED' === status) { | ||
| appRef.current?.unmount(); | ||
| } | ||
| removeGlobalUncaughtErrorHandler(errorHandler) | ||
| } | ||
| }, [microApp]) | ||
| }, [mfAppConfig, delayLoading]) | ||
| return ( | ||
| <div className='ttk-mf-app'> | ||
| {loading ? <Loading className='ttk-mf-app-spin' loading={loading} /> : null} | ||
| {error ? <Error className='ttk-mf-app-alert' message={errorMsg} description={errorDesc} /> : null} | ||
| <div className='ttk-mf-app-container' ref={ref}></div> | ||
| <div style={STYLE_APP}> | ||
| {(delayLoading || loading) && RenderLoading ? | ||
| <div style={STYLE_APP_SPIN}> | ||
| <RenderLoading loading={loading} /> | ||
| </div> | ||
| : null} | ||
| {error ? | ||
| <div style={STYLE_APP_ERROR}> | ||
| {RenderError ? <RenderError message={errorMsg} description={errorDesc} /> : | ||
| [<span style={STYLE_APP_ERROR_MSG}>{errorMsg}</span>, <span>{errorDesc}</span>]} | ||
| </div> | ||
| : null} | ||
| <div style={STYLE_APP_CONTAINER} ref={ref}></div> | ||
| </div> | ||
| ); | ||
| } |
+1
-1
| export * from './component'; | ||
| export * as lifecycle from './lifecycle'; |
| .ttk-mf-app { | ||
| width: 100%; | ||
| height: 100%; | ||
| overflow: hidden; | ||
| } | ||
| .ttk-mf-app-spin { | ||
| width: 100%; | ||
| height: 100%; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| } | ||
| .ttk-mf-app-alert { | ||
| margin: 10px; | ||
| } | ||
| .ttk-mf-app-container { | ||
| width: 100%; | ||
| height: 100%; | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
43036
74.45%3
-25%817
102.23%27
8%34
3.03%1
Infinity%- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed