一 问题
如何将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用。
二 微前端概念
微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。
三 MicroApp优势
1 使用简单
可以在基座应用中嵌入一行代码即可渲染一个微前端应用,还提供了js沙箱、样式隔离、元素隔离、预加载、数据通信、静态资源补全等一系列完善的功能。
2 零依赖
micro-app没有任何依赖,这赋予它小巧的体积和更高的扩展性。
3 兼容所有框架
在任何技术框架中都可以正常运行
四 效果演示
实际运行项目进行演示
五 基座应用使用方法
基座应用不限制技术栈,此基座以vue为例
1 初始化项目
此步骤使用脚手架工具快速搭建即可,省略
2 安装依赖
npm i @micro-zoe/micro-app --save
3 入口处引入
import microApp from '@micro-zoe/micro-app'
microApp.start({
// microApp生命周期
lifeCycles: {
created(e) {
console.log('created')
},
beforemount(e) {
console.log('beforemount')
},
mounted(e) {
console.log('mounted')
},
unmount(e) {
console.log('unmount')
},
error(e) {
console.log('error', e)
}
}
})
4 给子应用分配路由
const routes = [
{
path: '/',
name: 'base',
component: () => import("../views/base.vue"),
},
{
path: '/micro-app1/:page*', // vue-router@4.x path的写法为:'/my-page/:page*'
name: 'child1',
component: () => import("../views/app1.vue"),
},
{
path: '/micro-app2/:page*', // vue-router@4.x path的写法为:'/my-page/:page*'
name: 'child2',
component: () => import("../views/app2.vue"),
}
]
5 嵌入子应用
<!--
name(必传):应用名称,必须与第4步配置路由的name保持一致
url(必传):应用地址,会被自动补全为http://localhost:3000/index.html
baseroute(可选):基座应用分配给子应用的基础路由,就是上面的 `/micro-app1` 或者 `/micro-app2`
-->
<micro-app name='child1' url='http://localhost:8081/micro-app1' baseroute="/micro-app1"></micro-app>
六 子应用使用方法
子应用不限制技术栈,此基座以vue为例
1 设置基础路由
如果基座应用是history路由,子应用是hash路由,这一步可以省略
const router = createRouter({
history: createWebHistory(window.__MICRO_APP_BASE_ROUTE__ || process.env.BASE_URL),
routes: routes
})
2 创建公共路径引入文件,并在入口文件引入
// __MICRO_APP_ENVIRONMENT__和__MICRO_APP_PUBLIC_PATH__是由micro-app注入的全局变量
if (window.__MICRO_APP_ENVIRONMENT__) {
// eslint-disable-next-line
__webpack_public_path__ = window.__MICRO_APP_PUBLIC_PATH__
}
import './public-path'
3 配置项目跨域访问
devServer: {
headers: {
'Access-Control-Allow-Origin': '*',
}
}
七 提供功能
1 数据通信
micro-app提供了一套灵活的数据通信机制,方便基座应用和子应用之间的数据传输。
(1)子应用获取来自基座应用的数据
setup() {
const dataListener = (data) => {
console.log("来自基座应用的数据", data);
};
onMounted(() => {
// 绑定监听函数
window.microApp?.addDataListener(dataListener, true);
// 解绑监听函数
// window.microApp.removeDataListener(dataListener)
});
return {
dataListener
};
}
(2)子应用向基座应用发送数据
window.microApp?.dispatch({
type: "app1向基座发送的数据",
value: 123,
});
(3)基座应用向子应用发送数据
import microApp from "@micro-zoe/micro-app";
// child1为基座应用的name
microApp.setData("child1", {
type: "发送给app1的数据",
value: 123,
});
(4)基座应用获取来自子应用的数据
<template>
<micro-app
name='my-app'
url='xx'
// 数据在事件对象的detail.data字段中,子应用每次发送数据都会触发datachange
@datachange='handleDataChange'
/>
</template>
<script>
export default {
methods: {
handleDataChange (e) {
console.log('来自子应用的数据:', e.detail.data)
}
}
}
</script>
2 生命周期
(1)应用内生命周期
<template>
<micro-app
name='xx'
url='xx'
@created='created'
@beforemount='beforemount'
@mounted='mounted'
@unmount='unmount'
@error='error'
/>
</template>
<script>
export default {
methods: {
created () {
console.log('micro-app元素被创建'),
},
beforemount () {
console.log('即将被渲染'),
},
mounted () {
console.log('已经渲染完成'),
},
unmount () {
console.log('已经卸载'),
},
error () {
console.log('渲染出错'),
}
}
}
</script>
(2)全局生命周期
import microApp from '@micro-zoe/micro-app'
microApp.start({
lifeCycles: {
created (e) {
console.log('created')
},
beforemount (e) {
console.log('beforemount')
},
mounted (e) {
console.log('mounted')
},
unmount (e) {
console.log('unmount')
},
error (e) {
console.log('error')
}
}
})
3 环境变量
(1)判断是否处于微前端环境
window.__MICRO_APP_ENVIRONMENT__
(2)获取当前应用名称
window.__MICRO_APP_NAME__
(3)判断是否是基座应用
window.__MICRO_APP_BASE_APPLICATION__
八 其他
1 什么情况下需要用到微前端
多个团队采用不同技术栈并行开发;项目单独部署,单独维护。
2 iframe与微前端对比
(1)iframe的优缺点
iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。
优点:
- 完全隔离了css和js,避免了各个系统之间的样式和js污染。
- 可以在子系统完全不修改的情况下嵌入进来。
缺点:
- 页面加载问题: 影响主页面加载,阻塞onload事件,本身加载也很慢,页面缓存过多会导致电脑卡顿。
- 布局问题:iframe必须给一个指定的高度,否则会塌陷。解决办法:子系统实时计算高度并通过postMessage发送给主页面,主页面动态设置高度,修改子系统或者代理插入脚本。有些情况会出现多个滚动条,用户体验不佳。
(2)微前端的优缺点
优点:
- 技术无关性
- 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染
缺点:
- 子应用需按照规范进行少量改动,但是不影响子系统独立开发部署及其功能