虽然qiankun已经提供了微前端的一些基本能力,但是在使用过程中还是有很多问题需要关注。
项目架构规划
-
Git subtree或者多仓库:在子应用较多的情况可采用此方式,缺点是每次子应用变更后,聚合库还得同步一次变更。
18091274-44952db2fd681a3d
应用拆分粒度
微应用的拆与合思考:拆的是系统复杂度,合的是系统复用度。
拆分的时候可以从平台差异、页面结构、产品业务方面考虑。并不是越细越好,业务关联紧密的功能单元应该做成一个微应用,反之关联不紧密的可以考虑拆分成多个微应用。
样式隔离
使用qiankun默认的沙箱,仅能确保单实例场景子应用之间的样式隔离,但是无法确保主应用跟子应用、或者多实例场景的子应用样式隔离。目前还没有完美的解决方案,如果遇到样式污染问题,可以考虑如下方案:
- 命名规范+命名空间,可以尝试开启experimentalStyleIsolation(实验阶段)。
- ShadowDom:可以开启strictStyleIsolation严格模式,启用ShadowDom,但是这并不是一个可以无脑使用的方案,可能还会有一些其他问题,如子应用的弹窗挂载到body上时样式丢失。
- CSS In JS
- CSSModule
数据通信
应用间尽量避免通信,减少耦合性,如果两个应用间有频繁的通信需求,说明这两个微应用本身就是服务于同一个业务场景,合并成一个微应用可能会更合适。
微前端通信方式:
- 基于 URL:使用简单、通用性强,但能力较弱,不适用复杂的业务场景。
- 基于 Props:最核心的通信能力,能够满足一些简单的场景。适用于主子应用共享组件、公共方法调用等。
- GlobalState:基于发布订阅模式实现,能够满足比较复杂的场景。
- 本地Storage:仅适合静态通信场景,且 JSON.stringify()可能会造成数据丢失。
权限处理
主应用负责身份验证,拿到授权信息后下发到各微应用中,各应用再根据拿到的授权信息过滤各自路由信息。
资源共享
统一管理维护
将公共资源提取到一个地方,避免多个地方维护,但是仍然会多次打包。可以通过如下两种方式:
- file或link方式
- git仓库或者私服
依赖提取
在一个团队中,技术栈相对固定,所以统一技术栈很多基础依赖相对是固定的,但是默认情况下每个应用都会重复打包一次,会造成重复下载,影响运行性能。例如,如果每个微应用都包括自己的 Vue 副本,那么用户就得多次下载 Vue。
在进行如下改造之前,先确认是否有此必要,因为它会增加应用间的耦合性(如技术栈、依赖版本必须一致) ,而这是和微前端思想相悖的,
- cdn或者将公共依赖抽离成单独的应用或者文件引用。
- 由主应用下发(props或者window),需要处理子应用单独运行时依赖的来源问题。
部署与资源路径问题
部署方案
- 主应用和微应用部署到同一个服务器(同一个 IP 和端口)。
└── html/ # 根文件夹
├── child/ # 存放所有微应用的文件夹
| ├── app1/
| ├── app2/
├── index.html # 主应用的index.html
├── css/ # 主应用的css文件夹
├── js/ # 主应用的js文件夹
registerMicroApps([
{
name: 'app1',
entry: '/child/app1/', // http://localhost:8080/child/app1/
container: '#container',
activeRule: '/child-app1',
},
{
name: 'app2',
entry: '/child/app2/', // http://localhost:8080/child/app2/
container: '#container',
activeRule: '/child-app2',
}
],
- 主应用和微应用部署在不同的服务器,使用 Nginx 代理访问。
/app1/ {
proxy_pass http://www.b.com/app1/;
proxy_set_header Host $host:$server_port;
}
registerMicroApps([
{
name: 'app1',
entry: '/app1/', // http://localhost:8080/app1/
container: '#container',
activeRule: '/child-app1',
},
],
资源路径错误
在src代码中引用public资源会有问题,资源尽量放到src中,让webpack处理,注入publicPath。
<template>
<img src="../../assets/images/logo.png" alt="">
<div class="img-test"></div>
<div class="img-test2 test" :style="`background:url(${require('../../assets/images/logo.png')})`"></div>
<!-- 路径错误 -->
<img src="/logo.png" class="test" alt="">
</template>
<style scoped>
.img-test{
background: url('../../assets/images/logo.png') no-repeat;
background-size: 100% 100%;
width: 100px;
height: 100px;
}
</style>
应用之间跳转
在微应用中如果要进行应用间跳转,不能直接使用微应用的router,可以有如下几种方式:
- 将跳转动作上抛给主应用,由主应用进行切换。
- 将主应用router下发到微应用,微应用使用该router进行跳转动作。
- 使用原生方法改变url(不建议,会造成页面刷新)。
其他问题
- VueDevtools调试微应用问题,需要手动处理,但是还是会存在失效问题。
- 对vite构建的微应用支持还有缺陷,因为Vite暂时还不支持运行时修改资源路径和ESModule导致沙箱失效。
- 各应用间的风格和交互逻辑应该统一,因为对用户来说我们的应用仍然是一体的,要避免应用间给用户造成撕裂感。
- 运行差异性处理:如果微应用需要单独运行,需要考虑集成运行和单独运行的差异性,做一些hack兼容处理。