装载子应用的两种方式
子应用的装载有两种方式,我们上一节讲了第一种方式,使用路由绑定的方式:
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
fastRefresh: {},
qiankun: {
master: {
// 注册子应用信息
apps: [
{
name: 'app1',
entry: 'http://localhost:8001',
},
{
name: 'app2',
entry: 'http://localhost:8002',
},
],
// 配置微应用关联的路由
routes: [
{
path: '/app1',
microApp: 'app1',
},
{
path: '/app2',
microApp: 'app2',
},
],
},
},
});
今天我们来讲解另一种子应用的装载方式,使用 组件的方式。
官方文档中建议使用第一种方式来引入自带路由的子应用。使用第二种方式来引入不带路由的子应用。否则使用第二种方式需要自行关注微应用依赖的路由跟当前浏览器 url 是否能正确匹配上,不然很容易出现微应用加载了,但是页面没有渲染出来的情况。
在实践中我们发现第二种方式有个很重要的优势,就是在父子应用通信中可以很方便地支持动态数据的传递(应用通信会在第 3 节介绍),所以我们的微前端应用的子应用装载实际使用的是第二种方式。
使用 <MicroApp />
组件装载子应用
修改 umi 配置文件:
import { defineConfig } from 'umi';
import { APP_LIST } from './src/constants';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
fastRefresh: {},
qiankun: {
master: {
// 注册子应用信息
apps: APP_LIST,
},
},
});
其中 APP_LIST 的值为:
import { IApp } from '@/types';
export enum EAppPath {
app1 = '/qiankun-app1',
app2 = '/qiankun-app2',
}
export const APP_LIST: IApp[] = [
{
name: 'app1',
entry: 'http://localhost:8001',
path: EAppPath.app1,
},
{
name: 'app2',
entry: 'http://localhost:8002',
path: EAppPath.app2,
},
];
编写使用<MicroApp />
组件装载子应用的逻辑:
import React, { useMemo } from 'react';
import { Link, useLocation, MicroApp } from 'umi';
import { APP_LIST, EAppPath } from '@/constants';
const Layout: React.VFC = () => {
const location = useLocation();
const pathname = location.pathname;
const app = useMemo(() => {
const app = APP_LIST.find((item) => item.path === pathname);
return app;
}, [pathname]);
const hasApp = () => {
return Boolean(app?.name);
};
const appPathKeys = Object.keys(EAppPath) as (keyof typeof EAppPath)[];
return (
<div>
<div>
{appPathKeys.map((key) => {
const path = EAppPath[key];
return (
<div key={key}>
<Link to={path}>{path}</Link>
</div>
);
})}
</div>
{hasApp() && <MicroApp name={app?.name} />}
</div>
);
};
export default Layout;
这样,就完成子应用的装载啦。
微应用的 loading 动画与组件样式
你可以通过配置 autoSetLoading 的方式,开启微应用的 loading 动画。
<MicroApp name={app?.name} autoSetLoading />
默认情况下,当检测到你使用的是 antd 组件库时,loading 动画使用的是 antd Spin 组件。
如果你需要定制自己的 loading 动画,或者修改组件的样式,你可以这样处理:
<MicroApp
name={app?.name}
autoSetLoading
// 设置自定义 loading 动画
loader={(loading: boolean) => {
if (!loading) {
return null;
}
return <div>loading</div>;
}}
// 微应用容器 class
className="myContainer"
// wrapper class,仅开启 loading 动画时生效
wrapperClassName="myWrapper"
/>