这是我参与更文挑战的第23天,活动详情查看: 更文挑战
1,什么是微前端?
微前端就是将不同的功能按照不同的维度拆分成多个子应用,通过主应用来加载这些子应用,微前端的核心在于拆分,拆完后在整合。 可以把微前端的框架理解为:基座或者插座,上面有很多插孔,有单孔的插口,有三个孔的插口,不同的子应用通过不同的协议插入到插座里,各个子应用相互独立。
2,为什么要去使用?
-
不同团队间开发同一个应用技术栈不同
-
希望每个团队都可以独立开发,独立部署
-
项目中还有很多老的应用代码
我们可以将一个应该划分成若干个子应用,将子应用打包成一个个的lib, 当路径切换时加载不同的子应用。这样每一个子应用都是独立的,技术栈也不用做限制,从而解决前端协同开发的问题
3,当前有哪些流行的微前端框架?
(1)single-spa
2018年single-spa诞生了,single-spa是一个前端微服务化的javaScript前端解决方案,实现了路由劫持和应用加载,但本事没有处理样式隔离
(2)qiankun
2019年,qiankun基于single-spa,提供了更加开箱即用的API,优化了single-spa的缺点
(single-spa + sandbox + import-htm-entry)
做到了技术栈无关,并且接入简单,像iframe一样
总结: 子应用都可以独立构建,运行时动态加载,主子应用完全解藕,技术栈无关,靠的是协议接入,子应用必须导处bootstrap, mount, unmout方法
4,为什么不用iframe?
- 如果使用iframe, iframe中的子应用切换路由时用户刷新页面就回到了首页,体验非常不好
- 基于URL来进行数据传递,消息能力肉
- 基于CustomEvent实现通信
- 使用全局变量,进行通信
5,single-spa案例
父应用加载子应用,子应用需要实现bootstrap, mount, unmout,
这三个函数怎么生成了,可以应用single-spa,
子应用如果是vue项目:安装single-spa-vue
子应用如果是react项目: 安装single-spa-react
父应用安装: single-spa
子应用vue: npm install single-spa-vue
import singleSpaVue from 'single-spa-vue'
子应用React: npm install single-spa-react
import singleSpaReact frm 'single-spa-react'
父引入: npm install single-spa
Import { registerApplication, start } from 'single-spa'
复制代码
安装:
子应用: child-vue
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false
const appOptions = {
el: '#vue',
router,
store,
render: h => h(App)
}
const vueLifeCycle = singleSpaVue({
Vue,
appOptions
})
// 如果是父应用引用我
if(window.singleSpaNavigate) [
/* eslint-disable */
__webpack_public_path__ = 'http://localhost:10000/' // 如果是父引入我,添加这个域名
]
// 协议接入, 定义好了协议,父应用会加载这些方法
export const bootstrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount
// 我们需要父应用加载子应用,将子应用打包成一个个lib去给父应用使用
// 我们需要父应用加载子应用
// bootstrap, mount, unmount
复制代码
1, 子应用需要打包:新建配置vue.config.js
module.exports = {
configureWebpack: {
output: {
library: 'singleVue',
libraryTarget: 'umd'
},
devServer: {
port: 10000
}
}
}
复制代码
2, router/index.js 需要配置路由的加载基础路径, 所有的路由请求之前都需要添加/vue
const router = new VueRouter({
mode: 'history',
// base: process.env.BASE_URL,
base: '/vue',
routes
})
复制代码
父应用: parent-vue
1, App.vue 配置子应用加载的位置
<template>
<div id="app">
<router-link to="/vue">加载Vue应用</router-link>
<!-- 子应用加载的位置 -->
<div id="vue"></div>
</div>
复制代码
2, main.js配置注册子应用
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false
const appOptions = {
el: '#vue',
router,
store,
render: h => h(App)
}
const vueLifeCycle = singleSpaVue({
Vue,
appOptions
})
// 如果是父应用引用我
if (window.singleSpaNavigate) {
/* eslint-disable */
__webpack_public_path__ = 'http://localhost:10000/' // 如果是父引入我,添加这个域名
}
if (!window.singleSpaNavigate) { // 解决子应用可以独立运行的方法
delete appOptions.el
new Vue(appOptions).$mount('#app')
}
// 协议接入, 定义好了协议,父应用会加载这些方法
export const bootstrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount
// 我们需要父应用加载子应用,将子应用打包成一个个lib去给父应用使用
// 我们需要父应用加载子应用
// bootstrap, mount, unmount
复制代码
6,single-spa的漏洞
1, css隔离问题, 子应用之间样式有互相影响,需要隔离
动态的样式,应用切换时,需要移除老应用的样式
2,主应用和子应用之前的样式隔离
- 约定项目前缀
- Css-modules 打包时生成不冲突的选择器名
- Shadow Dom 真正意义上的隔离
- Css-in-js
后续更新学习总结qiankun框架