准备两个应用
初始化主应用
使用 pro 来快速的初始化主应用。
npm i @ant-design/pro-cli -g
pro create app
复制代码
选择版本
安装依赖:
$ cd app && yarn
$ yarn add @umijs/plugin-qiankun -D
复制代码
- PS 如果安装报错:error An unexpected error occurred ,请检查 npm 设置
- 设置为官方源
npm config set registry http://registry.npmjs.org
复制代码
配置主应用
配置子应用路由 config/routes.ts
{
name: 'subapp',
path: '/subapp',
microApp: 'subapp',
access: 'normalRouteFilter'
},
复制代码
开启 Umi UI(可选):
// 打开开发模式下页面右下角的小气泡,方便添加区块和模版等pro资产
$ tyarn add @umijs/preset-ui -D
// 或
$ npm install --save-dev @umijs/preset-ui
复制代码
初始化子应用
mkdir subapp && cd subapp
yarn create @umijs/umi-app
复制代码
package.json 设置名称
{
"name":"subapp",
}
复制代码
配置子应用
安装依赖
yarn add @umijs/plugin-qiankun -D
复制代码
配置子应用.umirc.ts
qiankun: {
slave: {},
},
复制代码
设置端口号.env
设置固定的端口号,可以固定路径,方便后面的配置使用
PORT=8002
复制代码
连接父子应用
在主应用 app 的 config/config.ts 添加配置
qiankun: {
master: {
apps: [
{
name: 'subapp',
entry: 'http://localhost:8002'
}
]
}
}
复制代码
- 启动项目后,页面一直loading 需调整页面结构
- 由于添加了qiankun ,dom结构发生了变化,需要将替换root 为 root-master
测试子应用路由的使用
- 补充子应用路由 .umirc.ts
routes: [
{
path: '/', component: '@/pages/index',
routes: [
{
path: '/child1',
component: '@/pages/Child1',
},
{
path: '/child2',
component: '@/pages/Child2',
},
],
},
],
复制代码
- 调整页面结构
src/pages/index.tsx
import { Link } from 'umi';
import styles from './index.less';
export default function IndexPage(props) {
return (
<div>
<div style={{ background: '#fff', padding: 10 }}>
子应用公共布局
<Link to='/child1'>child1</Link>
</div>
{props.children}
</div>
);
}
复制代码
- 添加嵌套页面
src/pages/Child1.tsx
import { Link } from 'umi'
function Child1() {
return (
<div>
Child1
<br />
<div>
<Link to='/child2'>前往Child2</Link>
</div>
<br />
<div>
<Link to='/'>返回子应用主页subapp</Link>
</div>
</div>
)
}
export default Child1
复制代码
- 添加嵌套页面
src/pages/Child2.tsx
import React from 'react'
function Child2() {
return (
<div>我是Child2</div>
)
}
export default Child2
复制代码
路由效果展示
父子级通信
需确保已安装
@umijs/plugin-model
或@umijs/preset-react
父应用安装
yarn add @umijs/plugin-model @umijs/preset-react
复制代码
父级:src/app.tsx
// 添加子应用初始参数
export function useQiankunStateForSlave() {
const [masterState, setMasterState] = useState<{ name: string }>();
useEffect(() => {
setMasterState({ name: '我是app的数据来给subapp比个✌️' });
}, []);
return {
masterState,
setMasterState
}
}
复制代码
子集调用 src/pages/index.tsx
import { Link, useModel, } from 'umi';
import { Button, Space } from 'antd'
export default function IndexPage(props) {
const masterProps = useModel('@@qiankunStateFromMaster');
return (
<div>
<div style={{ background: '#fff', padding: 10 }}>
<Space>
子应用公共布局
<Link to='/child1'>child1</Link>
<Button onClick={() => {
masterProps?.setMasterState({ name: 'subapp修改了数据' })
}}>修改主应用数据</Button>
</Space>
</div>
<div>{masterProps?.masterState?.name}</div>
{props.children}
</div>
);
}
复制代码
父子通信展示
部署时的跨域问题
本地访问的时候,使用localhost是可以正常访问,部署到测试环境出现CORS跨域问题,解决方案是通过配置子应用的Nginx 来解决。
server { // ....此处省略
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
index index.html index.htm;
}
}
复制代码
路由权限[access]
子项目应如何设置路由权限,即如果没有权限访问子应用的页面,应在路由上直接拦截,返回到403页面。
- 首先,父应用应针对子应用设置权限,以subapp项目为例:
const routes = [
//....
{
name: 'subapp',
path: '/subapp',
microApp: 'subapp',
access: 'normalRouteFilter' // 设置权限校验
},
]
复制代码
- 其次,在子应用中配置access.ts 文件。
- 子应用添加 layout 配置
layout: {
name: 'Matrix 矩阵',
locale: false,
siderWidth: 0,
// 不展示顶栏
headerRender: false,
// 不展示页脚
footerRender: false,
// 不展示菜单
menuRender: false,
// 不展示菜单顶栏
menuHeaderRender: false,
disableContentMargin: false,
flatMenu: true,
}
复制代码