为什么需要微前端?

1,083 阅读4分钟

这是我参与更文挑战的第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框架