1. Features of umijs/plugin-qiankun
✔︎ Based on qiankun
✔︎ Support both main application and sub application to use umi
✔︎ Support importing sub application through components
✔︎ Parent-child application communication
✔︎ Customize bootstrap(), mount() and unmount() when sub application is running
✔︎ Joint debugging of main application and sub application
✔︎ Nested sub-application
building page
1, building the main application (using umi with built-in layout)
2, building sub-applications (building multiple sub-applications (umi, vue)
Second, the main application effect
3. Build the main application
1. Create a project through official tools
yarn create @umijs/umi-app
Note: Umi has the following aliases built in:
@,项目 src 目录
@@,临时目录,通常是 src/.umi 目录
umi,当前所运行的 umi 仓库目录
react-router 和 react-router-dom,底层路由库,锁定版本,打包时所有依赖了他们的地方使用同一个版本
react 和 react-dom,默认使用 16.x 版本,但如果项目里有依赖,会优先使用项目中依赖的版本
2, install Qiankun plug-in
npm i @umijs/plugin-qiankun -D 或者 yarn add @umijs/plugin-qiankun -D
3. Modify the configuration and edit .umirc.ts, for example:
import {
defineConfig } from 'umi';
export default defineConfig({
title: 'qiankun-demo',
favicon: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202012%2F04%2F20201204182229_e1a0a.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1653034439&t=1a24e65fd2a3d82a7390ca82cfad6041', // 修改浏览器上的icon
nodeModulesTransform: {
type: 'none',
},
// 内置 antd,目前内置版本是 ^4.0.0
antd: {
// dark: true,
compact: true,
},
layout: {
name: '乾坤微应用demo', //产品名称
locale: false, //是否开启国际化,开启后路由配置的菜单名会被当做菜单名国际化的key
logo:'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fblog%2F202012%2F04%2F20201204182229_e1a0a.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1653034439&t=1a24e65fd2a3d82a7390ca82cfad6041'
},
routes: [
{
path: '/', component: '@/pages/index' },
{
path: '/dashboard',
name: '显示方式',
icon: 'dashboard',
routes: [
{
path: '/dashboard/analysis',
icon: 'AreaChartOutlined',
name: '微应用直接显示',
component: '@/pages/Dashboard/Analysis',
// 微应用直接显示
microApp: 'app2'
},
{
path: '/dashboard/monitor',
icon: 'DesktopOutlined',
name: '主应用中嵌套MicroApp',
// 在主应用中嵌套MicroApp
component: '@/pages/Dashboard/Monitor',
},
],
},
{
path: '/app1',
name: 'App1-umi子应用',
icon: 'RadarChartOutlined',
microApp: 'app1',
props: {
onClick: (event:number) => console.log(event),
name: 'App1-umi子应用props',
age: 1,
},
},
{
path: '/app2',
name: 'APP2-umi子应用',
icon: 'AreaChartOutlined',
microApp: 'app2',
props: {
onClick: (event:any) => console.log(event),
name: 'name: App2-umi子应用props',
age: 1,
},
},
{
path: '/app-vue',
name: 'vue子应用',
icon: 'DotChartOutlined',
microApp: 'qiankun-vue',
props: {
onClick: (event:any) => console.log(event),
name: 'name: vue子应用props',
age: 1,
},
},
{
path: '/vue-ayp',
name: 'anyapeng',
icon: 'smile',
microApp: 'vue-ayp',
props: {
onClick: (event:any) => console.log(event),
name: 'vue-ayp子应用props',
age: 1,
},
},
],
fastRefresh: {
},//快速刷新(Fast Refresh),开发时可以保持组件状态,同时编辑提供即时反馈。
qiankun: {
master: {
// 注册子应用信息
apps: [
{
name: 'app1', // 唯一 id
entry: '//localhost:8001', // html entry
},
{
name: 'app2', // 唯一 id
entry: '//localhost:8002', // html entry
},
{
name: 'qiankun-vue', // 唯一 id
entry: '//localhost:8888', // html entry
},
{
name: 'vue-ayp', // 唯一 id
entry: '//localhost:10000/', // html entry
},
],
},
},
});
4oo, build app.ts under the root directory. umi will automatically find the exposed useQiankunStateForSlave, and pass the props parameter of the routing configuration
Main application: for example
import {
useState} from 'react'
export function useQiankunStateForSlave() {
const [Number, setNumber] = useState({
});
return {
Number,
setNumber,
};
}
useModel routing, MicroApp common sub-application reception: for example
import {
useModel } from 'umi';
function MyPage() {
//useModel('@@qiankunStateFromMaster')进行接收参数
const masterProps = useModel('@@qiankunStateFromMaster');
const {
numberF, onChange } = masterProps
const onAdd = () => {
onChange()
}
return (
<div>
{
numberF ?
<div>
<Button onClick={
() => {
onAdd() }}>App1-umi本地应用点击加一</Button>
<div>{
numberF}</div>
</div>
:
'App1-umi本地应用无点击事件'
}
</div>
)
}
Fourth, sub-application construction
1. The sub-application built by umi
1, install Qiankun plug-in
npm i @umijs/plugin-qiankun -D 或者 yarn add @umijs/plugin-qiankun -D
2. Configure app.ts, create an app.ts without the root directory of app.ts, and expose the qiankun object
export const qiankun = {
// 应用加载之前
async bootstrap(props:object) {
console.log('app1-umi子应用bootstrap1111',props);
},
// 应用 render 之前触发
async mount(props:object) {
console.log('app1-umi子应用mount1111',props);
},
// 应用卸载之后触发
async unmount(props:object) {
console.log('app1-umi子应用卸载11111',props);
},
};
3. Configure .umirc.ts
import {
defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{
path: '/', component: '@/pages/index' },
{
path: '/app1/app2',
name: 'vue',
icon: 'DotChartOutlined',
microApp: 'app2'
},
],
fastRefresh: {
},
qiankun: {
slave: {
}, // 必写
master: {
// 注册子应用信息
apps: [
{
name: 'app2', // 唯一 id
entry: '//localhost:8002', // html entry
},
],
},
},
});
4. Configure .env to limit the port
PORT=8001
2. Sub-applications built by vue
1, install Qiankun plug-in
npm i @umijs/plugin-qiankun -D 或者 yarn add @umijs/plugin-qiankun -D
2, configure vue.config.js
const {
name } = require('./package');
const path = require('path')
module.exports = {
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
},
},
configureWebpack: {
// 设置别名
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
output: {
// 微应用的包名,这里与主应用中注册的微应用名称一致
library: `${
name}-[name]`,
// 将你的 library 暴露为所有的模块定义下都可运行的方式
libraryTarget: 'umd',
// 按需加载相关,设置为 webpackJsonp_MicroAppPlugin 即可
jsonpFunction: `webpackJsonp_vue`,
},
},
};
3, Expose the qiankun hook in main.js in the root directory
import Vue from 'vue'
import VueRouter from 'vue-router';
import routes from './router.js';
console.log(routes,'routes')
// import store from './store';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue'
Vue.use(ElementUI);
Vue.use(VueRouter)
Vue.config.productionTip = false
let router = null;
let instance = null;
function render(props = {
}) {
const {
container } = props;
router = new VueRouter({
// 微应用配置路由 基础路径
base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/',
mode: 'history',
routes,
});
instance = new Vue({
router,
// store,
render: (h) => h(App),
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
export async function bootstrap() {
console.log('vue子应用bootstrap');
}
export async function mount(props) {
console.log('vue子应用mount', props);
render(props);
}
export async function unmount(props) {
console.log('vue子应用卸载', props);
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
router = null;
}
4. Configure .env to limit the port
PORT=8001
Five, father-son application communication
1. Use MicroApp to communicate
1. Parent application
mport {
MicroApp } from 'umi';
import {
useState } from 'react';
import {
Button } from 'antd';
export default function IndexPage() {
const [ age ,setAge] = useState(1)
const onAdd = ()=>{
setAge(age+1)
}
return (
<div>
<Button onClick ={
()=>{
onAdd()}}>父应用增加年龄</Button>
<div>{
age}</div>
{
/* MicroApp 像props一样传参 */}
<MicroApp name="vue-ayp" onChange={
onAdd} age={
age} />
</div>
);
}
2. Sub-application
import {
useModel } from 'umi';
function MyPage() {
// useModel('@@qiankunStateFromMaster') 子应用可以在其内部全局拿到父应用传递过来的参数
const masterProps = useModel('@@qiankunStateFromMaster');
const {
numberF, onChange } = masterProps
const onAdd = () => {
onChange()
}
return (
<div>
{
numberF ?
<div>
<Button onClick={
() => {
onAdd() }}>App1-umi本地应用点击加一</Button>
<div>{
numberF}</div>
</div>
:
'App1-umi本地应用无点击事件'
}
</div>
)
}
2. Use routing to pass parameter communication (example on the official website)
A solution similar to the communication between components in react.
When configuring apps in the main application, pass the data through props
// src/app.js
export const qiankun = fetch('/config').then((config) => {
return {
apps: [
{
name: 'app1',
entry: '//localhost:2222',
props: {
onClick: (event) => console.log(event),
name: 'xx',
age: 1,
},
},
],
};
});
2. The sub-application obtains the props consumption data in the life cycle hook