1、项目搭建
通过vite构建4个应用,分别为:
basic-vue-app–(vue3基座应用)
micro-vue2-app–(vue2微应用)
micro-vue3-app–(vue3微应用)
micro-react-app–(react微应用)
打开我们的基座项目basic-vue-app 添加项目依赖,载入乾坤的包:
npm install qiankun
编写qiankun配置文件:
(1).搭建微应用的列表,进行注册
(2).启动qiankun
(3).在入口文件引入qiankun配置文件
import { registerMicroApps, start } from 'qiankun'
registerMicroApps([
{
name: 'vue3-app', // 必须与微应用注册名字相同
entry: import.meta.env.MODE === 'development' ? 'http://127.0.0.1:5174' : '/vue3-app/', // 入口路径,开发时为微应用所启本地服务,上线时为微应用线上路径
container: '#sub-app-container', // 微应用挂载的节点
activeRule: '/vue3-app', // 当访问路由为 /vue3-app 时加载微应用
props: {
msg: "我是来自主应用的值-vue3" // 主应用向微应用传递参数
}
},
{
name: 'vue2-app',
entry: import.meta.env.MODE === 'development' ? 'http://127.0.0.1:5176' : '/micro-vue2-app/',
container: '#sub-app-container',
activeRule: '/vue2-app',
props: {
msg: "我是来自主应用的值-vue2"
}
},
{
name: 'react-app',
entry: import.meta.env.MODE === 'development' ? 'http://127.0.0.1:5175' : '/micro-react-app/',
container: '#sub-app-container',
activeRule: '/react-app',
props: {
msg: "我是来自主应用的值-react"
}
}
])
start()
注册micro-vue2-app微应用:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
let instance = null;
const initQianKun = () => {
renderWithQiankun({
// 当前应用在主应用中的生命周期
// 文档 https://qiankun.umijs.org/zh/guide/getting-started#
mount(props) {
console.log('vue2微应用开始挂载了')
render(props.container)
// 可以通过props读取主应用的参数:msg 监听主应用传值
props.onGlobalStateChange((res) => {
store.count = res.count
console.log('来自主应用的count值:' + res.count)
})
},
bootstrap() {
console.log('-- bootstrap --')
},
update() {
console.log('-- update --')
},
unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
console.log('-- unmount --')
},
})
}
const render = (container) => {
// 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地
console.log('主应用的挂载节点' + container)
const appDom = container ? container.querySelector('#app') : "#app"
instance = new Vue({
router,
store,
render: (h) => h(App),
}).$mount(appDom);
}
// 判断当前应用是否在主应用中
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
注册micro-vue3-app微应用:
import { createApp } from 'vue'
import App from './App.vue'
import { store } from './store'
import router from './router'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const initQianKun = () => {
renderWithQiankun({
// 当前应用在主应用中的生命周期
// 文档 https://qiankun.umijs.org/zh/guide/getting-started#
mount(props) {
console.log('vue3微应用开始挂载了')
render(props.container)
// 可以通过props读取主应用的参数:msg
// 监听主应用传值
props.onGlobalStateChange((res) => {
store.count = res.count
console.log('来自主应用的count值:' + res.count)
})
},
bootstrap() {
console.log('-- bootstrap --')
},
update() {
console.log('-- update --')
},
unmount() {
console.log('-- unmount --')
},
})
}
const render = (container) => {
// 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地
console.log('主应用的挂载节点' + container)
const appDom = container ? container : "#app"
createApp(App).use(router).mount(appDom)
}
console.log('qiankunWindow对象')
console.log(qiankunWindow)
console.log(qiankunWindow.__POWERED_BY_QIANKUN__)
// 判断当前应用是否在主应用中
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
注册micro-react-app微应用:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const initQianKun = () => {
renderWithQiankun({
// 当前应用在主应用中的生命周期
// 文档 https://qiankun.umijs.org/zh/guide/getting-started#
mount(props) {
render(props.container)
// 可以通过props读取主应用的参数:msg
// 监听主应用传值
props.onGlobalStateChange((res) => {
console.log(res.count)
})
},
bootstrap() { },
unmount() { },
})
}
const render = (container) => {
// 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地
const appDom = container ? container : document.getElementById('root')
ReactDOM.createRoot(appDom).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
}
// 判断当前应用是否在主应用中
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
Vite配置:
以micro-vue2-app为例,部署在同一域名二级目录下需要设置base。
import { createVuePlugin } from 'vite-plugin-vue2';
import { defineConfig } from 'vite';
import qiankun from 'vite-plugin-qiankun'
// https://vitejs.dev/config/
export default ({ mode }) => {
return defineConfig ({
base: mode === 'development' ? './' : '/micro-vue2-app/',
resolve: {
alias: [{ find: '@', replacement: '/src' }],
},
server: {
host: '0.0.0.0',
port: 5176,
proxy: {
'/api': {
target: 'http://127.0.0.1:8000/api',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@import "@/assets/style/index.scss";`,
},
},
},
plugins: [
createVuePlugin(),
qiankun('vue2-app', { // 微应用名字,与主应用注册的微应用名字保持一致
useDevMode: true
}),
],
});
}
本地分别启动主应用和子应用:
以micro-vue2-app为例:激活路由为/vue2-app则加载vue2子应用挂载在基座应用指定容器内,子应用路由正常切换。
2、运维部署
本地window机器安装nginx:
https://nginx.org/en/download.html 下载nginx安装包解压到指定目录,启动nginx:
hosts文件配置本地ip映射域名:
C:\Windows\System32\drivers\etc下增加:
127.0.0.1 demofe.noahgroup.com
nginx的conf目录下新建conf.d目录,以域名为文件名新建文件:
nginx配置文件做如下更改,设置根目录为基座应用build后的dist文件夹:
重启nginx:
npm run build基座应用,浏览器输入域名:
分别打包micro-vue2-app,micro-vue3-app,micro-react-app,因为是部署在同一个域名下,有两种方案:
(1)、将打包后的dist文件分别copy到基座应用dist目录下,以子应用的enter为文件名命名:
(2)、nginx通过alias配置将子应用映射到相应的子目录,请注意将主应用和子应用的部署路径替换为实际的路径,以vue3-app为例:
重启nginx,浏览器查看,以micro-vue2-app为例,点击“进入Vue2-App应用的Home页” 进入到vue2微应用/home路由下:
以上就是将qiankun微前端基座应用和微应用部署在同一个域名下,主应用和微应用都可独立部署,如若分别部署在不同的域名下,将微应用入口entey改为独立部署的地址。
3、遇到问题
(1)、Vite中不能导出qiankun生命周期函数
- vite 构建的 js 内容必须在 type=module 的 script 脚本里;
- qiankun 的源码依赖之一 import-html-entry 则不支持 type=module 这个属性
- qiankun 是通过 eval 来执行这些 js 的内容,而 vite 里面 import/export 没有被转码, 所以直接接入会报错:不允许在非type=module 的 script 里面使用 import
方案一:
因为vite使用的rollup,所以我们使用可以使用rollup插件 rollup/plugin-html,然后修改vite.config.js中build的配置,把vite默认输出的target模式修改一下,将module改为esnext。有如下缺点:
- 可以实现生产环境接入,开发环境不行;
- vite没有动态publicPath的支持;所以 Vite.config 中 base 配置需要写死
- vite code-splitting(代码分割)功能并不支持iife和umd两种格式,导致路由无法懒加载;
- 图片资源只会被打包成 base64,无论图片大小
https://github.com/umijs/qiankun/issues/1268
方案二:(推荐)
vite-plugin-qiankun插件,https://github.com/tengmaoqing/vite-plugin-qiankun
- 保留 vite 构建 es 模块的优势
- 一键配置,不影响已有的 vite 配置
- 支持 vite 开发环境
修改vite.config.ts配置和main.ts中导出生命周期钩子如上。