微前端解决方案
目录
微前端解决方案
目录
1. 解决方案对比
目前前端技术领域已有多种成熟的 解决方案:
- iframe
- Web Components
- ESM
- single-spa
- qiankun
- EMP
- MicroApp
各解决方案对比如下:
- iframe 可以直接加载其他应用,但无法做到单页导致许多功能无法正常在主应用中展示。
- web Components 和 ESM(ES Module)是浏览器提供给开发者的能力,能在单页中实现微前端,不过后者需要做好代码隔离,并且他们都是浏览器的新特性,都存在兼容性问题,微前端方面的探索也不成熟,只能作为面向未来的微前端手段。
- 是通过监听 url change 事件,在路由变化时匹配到渲染的子应用并进行渲染,这个思路也是目前实现微前端的主流方式。同时 single-spa 要求子应用修改渲染逻辑并暴露出三个方法:bootstrap、mount、unmount,分别对应初始化、渲染和卸载,这也导致子应用需要对入口文件进行修改。
- 是基于 single-spa 进行封装,所以这些特点也被 qiankun 继承下来,并且需要对 webpack 配置进行一些修改。qiankun 基本上可以称为单页版的 iframe,具有沙箱隔离及资源预加载的特点,几乎无可挑剔。
- 作为最年轻微前端解决方案,也是吸收了许多 web 优秀特性才诞生的,它在实现微前端的基础上,扩充了跨应用状态共享、跨框架组件调用、远程拉取ts声明文件、动态更新微应用等能力。同时,细心的小伙伴应该已经发现,EMP 能做到第三方依赖的共享,使代码尽可能地重复利用,减少加载的内容。
- 并没有沿袭 single-spa 的思路,而是借鉴了 WebComponents 的思想,通过 CustomElement 结合自定义的 ShadowDom,将微前端封装成一个类 WebComponents 组件,从而实现微前端的组件化渲染。并且由于自定义 ShadowDom 的隔离特性,MicroApp 不需要像 single-spa 和 qiankun 一样要求子应用修改渲染逻辑并暴露出方法,也不需要修改 webpack 配置,是目前市面上接入微前端成本最低的方案。
2. MicroApp 解决方案示例
2.1 微应用注册
在项目主文件 main.js 中采用以下方式注册微应用:
if(!window.__MICRO_APP_ENVIRONMENT__){
microApp.start()
}
// 微应用模式
let app = null
export async function mount (props) {
app = new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
window.microApp.addDataListener((data) => {
// 当基座下发跳转指令时进行跳转
if (data.path) {
app.$router.push(data.path)
}
},true)
}
// 子应用独立运行时逻辑
export async function mountInChild(props) {
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
}
// 卸载应用
export async function unmount () {
app.$destroy()
app.$el.innerHTML = ''
app = null
}
// 微前端环境下,注册mount和unmount方法
// window.__MICRO_APP_ENVIRONMENT__ 为微应用标识
if (window.__MICRO_APP_ENVIRONMENT__) {
window[`micro-app-${window.__MICRO_APP_NAME__}`] = { mount, unmount }
} else {
// 非微前端环境直接渲染
mountInChild()
}
2.2 微应用获取 token 信息
- 获取 token
主应用通过单点登录方式登录,将 token 信息存入
sessionStorage 的 __storejs_pro___ACCESS_TOKEN 中:
// 子应用获取 token
sessionStorage.getItem('__storejs_pro___ACCESS_TOKEN')
2. 微应用 token 过期处理
微应用 token 过期需要做响应拦截,报告主应用 token 过期,报告主应用方法如下:
if(window.__MICRO_APP_ENVIRONMENT__){
window.microApp.dispatch({action:'logout'})
}
主应用接受到微应用的消息,弹出重新登录弹窗,用户点击登录可实现重新登录。
2.3 微应用允许跨域访问设置
微应用需要设置允许跨域访问主应用才能加载微应用的资源。
- 开发环境:
需要设置打包配置文件的 devServer 的 headers 属性
headers: {
'Access-Control-Allow-Origin': '*',
},
- 生产环境:
微应用nginx 需要配置: ‘Access-Control-Allow-Origin’: ‘主应用域名’ 或者 ‘Access-Control-Allow-Origin’: ‘*’
2.4 微应用获取cookie
微应用nginx 需要配置: ‘Access-Control-Allow-Origin’: ‘主应用域名’ ,主应用域名
不可为 ’*’
微应用nginx需要开启: ‘Access-Control-Allow-Credentials’:true
微应用接口请求需配置 baseURL: ‘ 微应用的服务地址 ’
微应用接口请求需允许 withCredentials:true
2.5 微应用全局通信
- 发送方
if (window.__MICRO_APP_ENVIRONMENT__) {
window.microApp.setGlobalData( data )
}
- 接收方
if (window.__MICRO_APP_ENVIRONMENT__) {
const data = window.microApp.getGlobalData()
}
2.6 资源复用
- 父应用资源的暴露
- 使用 url 引入的方式调用模块包,默认注册位置 public/index.html 入口文件
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>
- 于父框架微前端初始化时注册需要暴露的资源,默认注册位置 main.js
if(!window.__MICRO_APP_ENVIRONMENT__){
microApp.start(
{
globalAssets: {
js: ['https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js'], // js地址
// css: ['css地址1', 'css地址2', ...], // css地址
}
}
)
}
2. 子应用使用父级资源
于入口文件通过 url 方式引入和父框架一样地址的资源。
子应用相同地址的资源匹配到父框架时,便能直接使用父框架的资源,而无需自己加载,起到资源复用的作用。
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js"></script>