
qiankun微前端-vite方案
需求背景
项目中需要接入PPT编辑器的功能,最终的解决方案是接入开源的PPT编辑器:PPTist,这种接入是不可能把代码完全融合进来的,那些需要做的调整太多,我们要做的是以微服务的形式,将功能引入到主站内。
常用的解决方案有两种:
iframe
为什么不用 iframe,这几乎是所有微前端方案第一个会被 challenge 的问题。但是大部分微前端方案又不约而同放弃了 iframe 方案,自然是有原因的,并不是为了 "炫技" 或者刻意追求 "特立独行"。
如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。
iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
1. url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
2. UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..
3. 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
4. 慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。
其中有的问题比较好解决(问题1),有的问题我们可以睁一只眼闭一只眼(问题4),但有的问题我们则很难解决(问题3)甚至无法解决(问题2),而这些无法解决的问题恰恰又会给产品带来非常严重的体验问题, 最终导致我们舍弃了 iframe 方案。
微前端
微前端架构具备以下几个核心价值:
技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权
独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
独立运行时
每个微应用之间状态隔离,运行时状态不共享
实现细节
本次案例主应用和微应用技术栈均为:vue3X+vite6X,且需要注意的是,主应用不是传统意义上的基座,而是一个真实的应用,这是有本质区别的。
通用的微前端方案可以参考如下项目:https://github.com/kakajun/qiankun-vite-test
主应用
首先安装qiankun
pnpm install qiankun
具体策略是:在主应用中创建一个页面来装载微应用,首先要做的就是在router新建一个页面
{
path: '/ppt',
name: 'ppt',
component: () => import('@/views/ppt/index.vue'),
},
然后在页面中添加一个容器来存放微应用,容器的ID是指定的:
<template>
<!-- 容器的id。微应用配置的时候需要 -->
<div id="sub-container"></div>
</template>
然后是注册微应用,需要注意的是:activeRule一定要是和微应用匹配的,否则会报错
registerMicroApps([
{
container: '#sub-container',
name: 'ppt',
entry: '//localhost:5188',
activeRule: '/ppt',
},
])
整体代码:
<template>
<!-- 容器的id。微应用配置的时候需要 -->
<div id="sub-container"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { start } from 'qiankun'
import { registerMicroApps } from 'qiankun'
// 引入qiankun
const registerApps = () => {
try {
registerMicroApps([
{
container: '#sub-container',
name: 'ppt',
entry: '//localhost:5188',
activeRule: '/ppt',
},
])
} catch (err) {
console.log(err)
}
}
onMounted(() => {
registerApps()
// 开启qiankun
start({
// sandbox: {
// // sandbox: { strictStyleIsolation: true } // 严格隔离
// // experimentalStyleIsolation: true // 样式隔离
// }
})
})
</script>
微应用
首先安装 vite-plugin-qiankun
pnpm install vite-plugin-qiankun
在 vite.config.ts 中安装插件
import qiankun from 'vite-plugin-qiankun';
export default {
// 这里的 'myMicroAppName' 是子应用名,主应用注册时AppName需保持一致
plugins: [qiankun('myMicroAppName')],
// 生产环境需要指定运行域名作为base
base: 'http://xxx.com/'
}
在入口文件里面写入乾坤的生命周期配置
// main.ts
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';
// some code
renderWithQiankun({
mount(props) {
console.log('mount');
render(props);
},
bootstrap() {
console.log('bootstrap');
},
unmount(props: any) {
console.log('unmount');
const { container } = props;
const mountRoot = container?.querySelector('#root');
ReactDOM.unmountComponentAtNode(
mountRoot || document.querySelector('#root'),
);
},
});
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render({});
}
dev下作为子应用调试
qiankun('viteapp', {
useDevMode
})