一、搭建项目基础结构
- 创建文件夹,在文件夹下新建main、react、vue、node四个文件夹
- 使用
create @umijs/umi-app创建main和react下的react项目 - 使用
vue create vue创建vue项目
二、引入qiankun
- main和react下引入
@umijs/plugin-qiankun,main下引入qiankun
三、配置qiankun
1.main配置
- 我们参考 umijs.org/zh-CN/plugi… 在主项目main的.umirc.ts 或 config/config.ts文件下修改,添加代码如下
routes: [
{
path: '/', component: '@/pages/index',
routes: [
{
path: '/sub-react',
microApp: 'react',
},
{
path: '/sub-vue',
microApp: 'vue',
},
]
},
],
qiankun: {
master: {
// 注册子应用信息
apps: [
{
name: 'react', // 唯一 id
// entry: '//localhost:8080/react/', // 打包后配置
entry: '//localhost:7001/', // html entry
},
{
name: 'vue', // 唯一 id
// entry: '//localhost:8080/vue/', // 打包后配置
entry: '//localhost:7002/', // html entry
},
],
},
},
outputPath: '../node/webapp',
在index中添加路由跳转代码,可以参考如下
<Button onClick={() => history.push('/sub-react')}>react</Button>
<Button onClick={() => history.push('/sub-vue')} style={{marginLeft: 12}}>vue</Button>
<div>{children}</div>
2.react配置
- 在react目录下的.umirc.ts 或 config/config.ts文件下修改
qiankun: {
slave: {}
},
publicPath: process.env.NODE_ENV === 'production' ? '/react/' : '/',
base: '/react',
outputPath: '../node/public/react',
src下新建app.ts文件,添加子应用启动生命周期
export const qiankun = {
// 应用加载之前
async bootstrap(props: any) {
console.log('app1 bootstrap', props);
},
// 应用 render 之前触发
async mount(props: any) {
console.log('app1 mount', props);
// props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
// console.log(state, prev);
// });
// props.setGlobalState(state);
},
// 应用卸载之后触发
async unmount(props: any) {
console.log('app1 unmount', props);
},
};
react根目录下新建.env文件配置PORT=7001
3.vue配置
- 在vue中新建.env文件配置
VUE_APP_PORT=7002新建vue.config.js文件,配置
const { name } = require('./package.json')
module.exports = {
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
}
},
devServer: {
port: process.env.VUE_APP_PORT,
headers: {
'Access-Control-Allow-Origin': '*' // 主应用获取子应用时跨域响应头
}
},
publicPath: process.env.NODE_ENV === 'production' ? '/vue/' : '/',
outputDir: '../node/public/vue',
assetsDir: 'static',
}
src文件夹下新增public-path.js文件,添加代码
主要是配置webpack的__webpack_public_path__参数
(function() {
console.log('----->', window.__POWERED_BY_QIANKUN__, process.env.VUE_APP_PORT);
if (window.__POWERED_BY_QIANKUN__) {
if (process.env.NODE_ENV === 'development') {
// eslint-disable-next-line no-undef
__webpack_public_path__ = `//localhost:${process.env.VUE_APP_PORT}/`;
return;
}
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
})();
router文件里改为导出routes,目的是为了在main.js下为VueRouter添加base等其它属性
修改main.js文件,改为
import Vue from 'vue'
import App from './App.vue'
import routes from './router'
import store from './store'
import './public-path'
import VueRouter from 'vue-router'
Vue.config.productionTip = false
let instance = null
function render (props = {}) {
const { container, base } = props
console.log(base);
console.log(window.__POWERED_BY_QIANKUN__, props, process.env.BASE_URL);
const router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? base : process.env.BASE_URL,
mode: 'history',
routes,
})
// if (window.__POWERED_BY_QIANKUN__) {
// router.beforeEach((to, from, next) => {
// if (to.path.includes('/sub-vue')) {
// next({
// path: '/sub-vue/' + to.path
// })
// } else {
// next()
// }
// })
// }
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] vue app bootstraped')
}
export async function mount (props) {
console.log('[vue] props from main framework', props)
// props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
// console.log('阿水大把大把', state, prev);
// });
render(props)
}
export async function unmount () {
instance.$destroy()
instance.$el.innerHTML = ''
instance = null
}
4.node配置
添加package.json文件,其中包含的包, express和koa选择想要的
"scripts": {
"start": "nodemon app.js",
},
"dependencies": {
"connect-history-api-fallback": "^1.6.0", // express
"express": "^4.17.1", // express
"koa": "^2.7.0", // koa2
"koa-static": "^5.0.0", // koa2
"koa2-connect-history-api-fallback": "^0.1.3" // koa2
},
"devDependencies": {
"nodemon": "^1.19.1"
}
新建app.js文件,文件内容如下
const Koa = require('koa');
const { historyApiFallback } = require('koa2-connect-history-api-fallback');
const app = new Koa();
const Static = require('koa-static');
const port = 8080;
app.use(historyApiFallback({
htmlAcceptHeaders: ['index/html', 'application/xhtml+xml']
}));
// 托管静态资源
app.use(Static(__dirname + '/public'))
app.use(Static(__dirname + '/webapp'))
app.listen(port, () => {
console.log(`服务已启动监听端口:${port}`)
}).on('error', (err) => {
throw err
});
// 下面是express的
// const express = require('express');
// const app = express();
// const history = require('connect-history-api-fallback');
//
// const port = 8080;
// app.use(history({
// htmlAcceptHeaders: ['index/html', 'application/xhtml+xml']
// }));
// app.use(express.static(__dirname + '/public'))
// app.use(express.static(__dirname + '/webapp'))
//
// app.listen(port, () => {
// console.log(`服务已启动监听端口:${port}`)
// })
5.测试、打包部署
在main、react、vue下执行npm start查看效果、访问localhost:8000、localhost:7001、localhost:7002
在main、react、vue下执行npm run build,启动node,在node下执行npm start
访问http://localhost:8080/查看效果
6.hash配置
umi搭建的请设置 history: {type: "hash"},
vue在创建VueRouter时设置mode: 'hash'
四、数据传递
在mian/src下新建app.ts,代码入下
import { initGlobalState } from 'qiankun';
const state = {
userId: 'userId-123',
userName: 'userName-123',
}
// 初始化 state
const actions = initGlobalState(state);
export async function getInitialState() {
return actions;
}
页面上设置状态
import {useModel} from "umi";
const { initialState } = useModel('@@initialState');
// 设置
initialState.setGlobalState({
userId: 'userId-321',
userName: '新值',
});
initialState.offGlobalStateChange();
子应用可以在生命周期中来监听状态值变化时、或者设置状态值
async mount(props: any) {
console.log('app1 mount', props);
props.onGlobalStateChange((state, prev) => {
// state: 变更后的状态; prev 变更前的状态
console.log(state, prev);
});
// props.setGlobalState(state);
},
更多api请参考官方文档 qiankun.umijs.org/zh/api/#sta…