微前端
概念
微前端借鉴了微服务的概念,将一个庞大的应用拆分成多个灵活的小应用,每个应用都可以独立开发,独立运行,独立部署,还可以随意组合,这样减低了耦合度,从而更加灵活
特性
可以多团队,不限技术栈,相互之间互不依赖
技术栈无关
主框架不限制接入的技术栈,子应用可自主选择技术栈(vue、react)
独立开发/部署
各个团队之间仓库独立,单独部署,互不依赖
增量升级:
具备渐进式升级的特性(简称需要啥装啥)
独立运行时
微应用之间运行时互不依赖,有独立的状态管理
微前端方案
iframe 方案
特点
- 接入比较简单
- 隔离非常稳
不足
- dom 割裂感严重,弹窗只能在 iframe,而且有滚动条
- 通信麻烦
- 前进后退按钮无效
qiankun 方案
qiankun 方案是基于 single-spa 的微前端方案。
micro-app 方案
micro-app 是基于 webcomponent + qiankun sandbox 的微前端方案。
EMP 方案
EMP 方案是基于 webpack 5 module federation 的微前端方案。
无界微前端 方案
特点
- 接入简单,代码量少
- 不需要针对 vite 额外处理
- 预加载
- 应用保活机制
不足
- 隔离 js 使用一个空的 iframe 进行隔离
- 子应用 axios 需要自行适配
- iframe 沙箱的 src 设置了主应用的 host,初始化 iframe 的时候需要等待 iframe 的 location.orign 从'about:blank'初始化为主应用的 host,这个采用的计时器去等待的不是很优雅。
参考网址
无界:https://wujie-micro.github.io/doc/
微前端:https://juejin.cn/post/7212603829572911159?searchId=20240311102708740158C08B84D2A1BC4C#heading-10
创建主应用
shnpm init vue
创建子应用
shnpm init vite
初始化项目
shpnpm init
生成 package.json
monorepo 架构
采用的是微前端一个主应用,和多个子应用,我们采用 monorepo 架构 一次 install 即可安装完成。
不用一个一个去 install 安装依赖
第一步 安装 pnpm
全局安装 pnpm
shnpm i pnpm -g
第二步 配置 Monorepo
在根目录新建一个 pnpm-workspace.yaml 配置依赖项
packages:
# all packages in direct subdirs of packages/
- 'main'
# all packages in subdirs of components/
- 'web/**'
配置完成后 install 一次就行
他会把所有的公共依赖项抽到外层,而里层的依赖项都是一些最核心的
安装依赖
shpnpm i
最外部的公共依赖包含所有
里层只会放进去项目对应的相关的依赖
很厉害
创建公共文件
创建了一个 utils
名字需要是 index
初始化
shpnpm init
配置 Monorepo
packages:
# all packages in direct subdirs of packages/
- 'main'
# all packages in subdirs of components/
- 'web/**'
# 新增 公共文件 - utils
- 'utils'
创建 request
用来封装 axios
安装 axios
shpnpm i axios
建立链接 main--utils
sh# main 建立连接 pnpm -F main add utils # main 建立连接 pnpm -F react add utils # main 建立连接 pnpm -F vue add utils
引用公共文件
在 main.js 文件中可以引用
子应用相同
无界-微前端
安装依赖
在主应用中安装 无界的包
pnpm i wujie
默认库为 pnpm i wujie
无界文档有常用框架封装好的 不需要手动封装, pnpm 安装 下面的就好
sh# vue2 框架 pnpm i wujie-vue2 -S # vue3 框架 pnpm i wujie-vue3 -S # react 框架 pnpm i wujie-react -S
在主应用中引入 什么框架安装什么就好
引入依赖
第一步 引入 引入对应的框架(这里是 vue3)
第二步 挂载
启动应用
启动主应用与子应用
shpnpm run dev
效果
无界-传参(项目之间的通信)
三种传参方式
通过 window 进行通讯
通过 window.parent.name 接收参数
// 主应用定义变量
window.name = ref('明楼');
// 子应用 vue3
const name = ref(window.parent.name); // 明楼
// 子应用 react
const [name] = useState(window.parent.name); // 明楼
通过 Props 给子应用注入参数
通过在 Wujie 组件上 通过 props 进行传参
<WujieVue
:props="{name:'明楼',age:26}"
url="http://127.0.0.1:5174/"
name="vue3" />
接收通过 window.$wujie.props 获取
// vue3
let obj = ref(window.$wujie.props);
// react
错误处理 TS 文件中 $wujie 会报错
// 报错$wujie 可以添加声明文件 在minjs中
declare global {
interface Window {
$wujie:{
props:Record<string,any>
}
}
}
event Bus
创建 事件总线 event bus
// 主应用 接收数据
bus.$on('vue', (data: any) => {
console.log(data);
});
bus.$on('React', (data: any) => {
console.log(data);
});
// 子应用 发送数据
// vue3
let data = ref('我是Vue3的数据');
const send = () => {
window.$wujie.bus.$emit('vue', data.value);
};
// react
<button
onClick={() => {
window.$wujie.bus.$emit('React', '我是React');
}}>
我是React的按钮
</button>;