微前端是什么?
背景
1、微前端架构旨在解决
单体应用在一个相对长的时间跨度下,由于参与的人员、团队的增多、变迁,从一个普通应用演变成一个巨石应用(Frontend Monolith)后
,随之而来的应用不可维护的问题
。这类问题在企业级 Web 应用中尤其常见。
2、微前端是一种类似于微服务的架构
,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。
核心价值
1、不限制技术栈
:主框架不限制接入应用的技术栈,微应用具备完全自主权
2、独立开发、独立部署
:微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
3、增量升级(拓展)
:在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术
4、升级或重构
:而微前端是一种非常好的实施渐进式重构的手段和策略
5、独立运行
:每个微应用之间状态隔离,运行时状态不共享
目前微前端的几种解决方案
iframe
优点:
1、最稳定的、上手难度最低的。
2、提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决
缺点:
1、url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
2、加载是另一个window窗口,页面缩放时内部窗口内部缩放不同步,以及弹窗无法全局覆盖,和双滚动条问题;
3、通信复杂;要用postMessage,另外发送消息时需要在onload监听事件处理,会出现发送额外的噪声消息的情况只适合简单的页面渲染
阿里乾坤 qiankun (阿里 14.2k)
官网地址
基于 single-spa 的微前端实现库,通过监听 url change 事件,在路由变化时匹配到渲染的子应用并进行渲染,这个思路也是目前实现微前端的主流方式。
特点:
1、基于 single-spa 封装,提供了更加开箱即用的 API。
2、技术栈无关,任意技术栈的应用均可 使用/接入,不论是React/Vue/Angular/JQuery 还是其他等框架。
3、HTML Entry 接入方式,让你接入微应用像使用 iframe 一样简单。
4、样式隔离,确保微应用之间样式互相不干扰。
5、JS 沙箱,确保微应用之间 全局变量/事件 不冲突。
6、资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度。
7、umi 插件,提供了 @umijs/plugin-qiankun 供 umi 应用一键切换成微前端架构系统。
不足:
1、 适配成本比较高,工程化、生命周期、静态资源路径、路由等都要做一系列的适配工作;
2、css 沙箱采用严格隔离会有各种问题,js 沙箱在某些场景下执行性能下降严重;
3、无法同时激活多个子应用,也不支持子应用保活;
4、无法支持 vite 等 esmodule 脚本运行;
microApp (京东 4k)
官网地址
micro-app是京东零售推出的一款微前端框架,它基于类WebComponent
进行渲染,从组件化的思维实现微前端。
核心功能在CustomElement基础上进行构建,CustomElement用于创建自定义标签,并提供了元素的渲染、卸载、属性修改等钩子函数,我们通过钩子函数获知微应用的渲染时机,并将自定义标签作为容器,微应用的所有元素和样式作用域都无法逃离容器边界,从而形成一个封闭的环境。
特点:
1、JS 沙箱。
2、样式隔离。
3、元素隔离。
4、预加载。
5、资源地址补全。
6、插件系统。
7、数据通信。
8、与技术栈无关
9、支持子应用保活
不足:
1、接入成本较 qiankun 有所降低,但是路由依然存在依赖;
2、多应用激活后无法保持各子应用的路由状态,刷新后全部丢失;
3、css 沙箱依然无法绝对的隔离,js 沙箱做全局变量查找缓存,性能有所优化;
4、支持vite运行,但必须使用plugin改造子应用,且 js 代码没办法做沙箱隔离;
5、对于不支持 webcompnent 的浏览器没有做降级处理;
无界:(腾讯 2k)
官网地址
无界微前端方案基于 webcomponent 容器
+ iframe 沙箱
,能够完善的解决适配成本、样式隔离、运行性能、页面白屏、子应用通信、子应用保活、多应用激活、vite 框架支持、应用共享等用户的核心诉求。
小结
除了Iframe,乾坤
,microApp
,无界
三个框架都可以实现JS 沙箱,样式隔离,数据通信的功能,并且任意技术栈的应用均可 使用/接入。
结合目前的实际工作情况(vue2,webpack),下面以vue进行demo测试JS 沙箱
,样式隔离
,数据通信
,(子应用保活)
的功能。
microApp基础示例
1. 基座应用
1. 依赖版本
npm i @micro-zoe/micro-app --save
文章来源:https://www.toymoban.com/news/detail-408565.html
"@micro-zoe/micro-app": "^0.8.10",
"vue": "^2.6.11",
2. main.js引入
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// 引入element
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// 引入microApp--start
import microApp from '@micro-zoe/micro-app'
microApp.start()
// 引入microApp--end
Vue.config.productionTip = false
Vue.use(ElementUI)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
3. router/index.js路由设置
import Vue from 'vue'
import VueRouter from 'vue-router'
import Layout from '../views/Layout.vue'
import MyPage from '../views/my-page.vue'
import Parent1 from '../views/parent1.vue'
import Parent2 from '../views/parent2.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
redirect: '/layout'
},
{
path: '/layout', // 基座项目的父路由
name: 'layout',
component: Layout,
redirect: '/layout/parent1',
children: [
{
path: 'parent1', // 基座项目的子路由1
name: 'parent1',
component: Parent1
},
{
path: 'parent2', // 基座项目的子路由2
name: 'parent2',
component: Parent2
},
{
// 👇 非严格匹配,/layout/my-page/* 都指向 MyPage 页面
path: 'my-page/:page*', // 微服务的路由
name: 'my-page',
component: MyPage
}
]
}
// {
// path: '/my-page/:page*',
// name: 'my-page',
// component: MyPage
// }
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
4. 各页面的内容
4.1 Layout.vue页面
<template>
<div>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="/layout/parent1">parent路由1</el-menu-item>
<el-menu-item index="/layout/parent2">parent路由2</el-menu-item>
<el-menu-item index="/layout/my-page/">children1-vue路由</el-menu-item>
</el-menu>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'layout',
data () {
return {
activeIndex: '/layout/parent1'
}
},
methods: {
handleSelect (key, keyPath) {
this.$router.push({ path: key })
}
},
created () {
// 刷新路由保持当前状态
this.activeIndex = this.$route.path
}
}
</script>
<style scoped>
</style>
4.2 my-page.vue页面
<template>
<div>
<h1>父应用页面----子应用</h1>
<!--
name(必传):应用名称
url(必传):应用地址,会被自动补全为http://localhost:3000/index.html
baseroute(可选):基座应用分配给子应用的基础路由,就是上面的 `/my-page`
-->
<micro-app
name="app1"
url="http://localhost:3000/"
baseroute="/my-page"
></micro-app>
</div>
</template>
<script>
export default {
name: 'my-page'
}
</script>
<style scoped>
</style>
4.3 parent1.vue和parent2.vue页面
<template>
<div>parent【1】</div>
</template>
<script>
export default {
name: 'parent1'
}
</script>
<style scoped>
</style>
2. 子应用
1. router/index.js路由设置
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = new VueRouter({
mode: 'history',
// 👇👇👇👇👇 __MICRO_APP_BASE_ROUTE__ 为micro-app传入的基础路由.子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座下发的baseroute
base: window.__MICRO_APP_BASE_ROUTE__ || process.env.BASE_URL,
routes
})
export default router
2. vue.config.js设置跨域支持
module.exports = {
devServer: {
port: 3000,
headers: {
'Access-Control-Allow-Origin': '*'
}
}
}
3. main.js引入自定义public-path.js文件
// main.js
import './public-path'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
const app = new Vue({
router,
render: (h) => h(App)
}).$mount('#app')
// 监听卸载操作
window.addEventListener('unmount', function () {
app.$destroy()
})
4. public-path.js文件
// public-path.js
// __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__
}
3. 注意事项
-
name(my-page.vue)
必须以字母开头,且不可以带有除中划线和下划线外的特殊符号 -
url只是html地址
,子应用的页面渲染还是基于浏览器地址的 -
baseroute
的作用请查看官网路由配置 - 子应用必须支持跨域访问,跨域配置参考这里
- 官网地址
乾坤示例
参考链接:https://blog.csdn.net/weixin_43193877/article/details/125717755文章来源地址https://www.toymoban.com/news/detail-408565.html
到了这里,关于Vue:关于微前端的整合的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!