关于微前端的几大特性技术选型分析

前言

本文主要分析对比了 MicroAppQiankun 两大微服务框架,从各方面需求特性上分析每个框架的优缺点,每个微服务特性的方案的技术选型。最后如何根据自己的业务需求,选择适合自己的微服务框架,以及如何实现自己的微服务框架。

  • Micro App
  • Qiankun
    • 蚂蚁金服 qiankun.umijs.org/zh
    • 基于 single-spa,弥补了不足,现在主流的微前端方案。

特性1. 加载子应用机制

MicroApp

js 复制代码
// router.js
import { BrowserRouter, Switch, Route } from 'react-router-dom'
import MyPage from './my-page'

export default function AppRoute () {
  return (
    <BrowserRouter>
      <Switch>
        // 👇 非严格匹配,/my-page/* 都指向 MyPage 页面
        <Route path='/my-page'>
          <MyPage />
        </Route>
      </Switch>
    </BrowserRouter>
  )
}

// my-page.js
export function MyPage () {
  return (
    <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>
  )
}
  • 通过 micro-app Web Components 自定义组件,将子应用页面嵌入到对应dom中。
  • 两种机制:
    • 基于路由配置:先在主应用里自己定义路由(比如react router),然后在路由组件里使用 micro-app,子应用里可以再定义子路由。
    • 一个页面多个子应用:一个页面下使用多个 micro-app组件,
  • 渲染子应用机制:
    1. 渲染 micro-app Web Components 初始化
    2. 组件通过fetch url,获取子应用的html;
    3. 分解处理html文本,获取css和js的资源地址;
    4. 通过fetch获取子应用的静态资源,也就是js和css的内容文本;
    5. 将处理过的html放入webComponent容器中,head放到micro-app-head dom里,body放到micro-app-body dom里;
    6. 给css加上 scope 前缀,并append到micro-app-head中;(样式隔离)
    7. 执行沙箱机制,在沙箱中执行js代码;(JS沙箱隔离)
    8. 完成子应用的初始化;

Qiankun

js 复制代码
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react app', // app name registered
    entry: '//localhost:7100',
    container: '#yourContainer',
    activeRule: '/yourActiveRule',
  },
  {
    name: 'vue app',
    entry: { scripts: ['//localhost:7100/main.js'] },
    container: '#yourContainer2',
    activeRule: '/yourActiveRule2',
  },
]);

start();
  • 两种机制:
    • 基于路由配置:基于 single-spa,通过注册微应用方式(registerMicroApps),把路由path跟子应用关联起来,跳转对应路由时,微应用就会被插入到指定的container(dom)中。同时依次调用微应用暴露出的生命周期钩子。微应用里可以再定义子路由。
    • 手动加载微应用:也支持一个页面同时存在多个微应用(loadMicroApp),也就是不依赖路由。
  • 渲染子应用机制:
    1. 原理总体跟MicroApp类似,只是实现机制不一样。
    2. 路由层监听主要还是基于 single-spa 实现的,包括生命周期,Qiankun只是额外实现了解析html,获取和增强生命周期,隔离JS等操作,跟MicroApp类似。

特性2. 技术栈

MicroApp

  • 用Web Components我理解好处是它可以不依赖框架,不用每个框架都写个组件,用一个原生组件维护就行。
    • 如果想定义路由,可以用React或Vue框架;或者应该也有方法不用纯js定义路由,不需要Webpack编译。
  • 主子应用可以用不同的框架,或者无框架。
  • 有Shadow DOM机制,但官方不建议用。

Qiankun

  • 因为自身支持路由,主应用不用定义路由机制,更不依赖框架。
  • 主子应用可以用不同的框架,或者无框架。
  • 虽然没用Web Components,不过内部也有Shadow DOM机制,但官方不建议用。

特性3. 样式隔离

方案选型:

  1. Shadow DOM
    • 实现:JS原生。
    • 优点:原生隔离。
    • 缺点 :无法引用外部样式,需要额外加处理逻辑实现;兼容不好,下面举例:
      • 一些弹窗组件会把dom挂在到document.body上,会导致元素逃离了阴影边界,跑到了主应用里面,样式就丢了。
      • React框架的事件代理问题。React 17已支持 github.com/facebook/re...
  2. BEM规范,给样式加前缀
    • 实现:开发内部给子应用样式统一加前缀。
    • 优点:无污染;可以引用或覆盖外部样式。
    • 缺点:需要各应用team约定规范前缀,尽量安排专人控制好scope,不要乱用滥用。
  3. css scope,给子应用所有样式加一层选择器来隔离样式
    • 实现:
      1. 通过fetch读取子应用css文件内容,批量加scope;(MicroApp、Qiankun)
      2. 或者通过自定义Webpack loader\plugin等方式,在编译层加scope;(一种想法,还未找到类似实现)
    • 优点:无污染,可控高;可以引用或覆盖外部样式。
    • 缺点:需要加比较复杂逻辑实现;同样有上面说的弹框dom挂载body样式丢失问题,需要common控件做适配。
  4. css modules
    • 优点:class name编译哈希字符串,独立无污染。
    • 缺点:需要Webpack等构建工具支持;无法被重写覆盖,比如子应用重写覆盖主应用样式。(建议主应用common或layout样式用class name,其它用css modules)

MicroApp

  • 通过fetch请求子应用html里的内外联样式,批量添加前缀,再引用到主html里,从而实现css scope机制。
  • 默认支持css scope,配合css modules。
  • 支持配置开启Shadow DOM,开启后css scope失效,但官方不建议开启。
  • 主应用样式默认全局,可以被子应用使用;子应用样式独立,只能自己使用。可以通过叹号魔法注释配置隔离。

官方:Shadow DOM具有更好的隔离性,但一些框架(如React)对Shadow DOM的兼容性不好,请谨慎使用。

Qiankun 有4种

  1. 动态切换样式表。
  2. css modules。
  3. 可选:严格样式隔离:Shadow DOM,同上会有兼容问题。sandbox.strictStyleIsolation
  4. 可选:scoped css:目前该特性还处于实验阶段。sandbox.experimentalStyleIsolation

特性4. JS沙箱隔离

方案选型:

  1. window快照:主要用于不支持Proxy的低版本浏览器;性能差;只支持单微服务模式,也就是一个页面只能存在一个子应用。
  2. 基于Proxy的沙箱:function + proxy + with
  3. iframe

MicroApp

  • 基于Proxy的沙箱。

Qiankun

  • 旧版本用的是快照机制,新版本是基于Proxy的沙箱。

特性5. 元素DOM隔离

一般只在一个页面有多个子应用情况下需要考虑,比如在两个应用里有重复的id或class的DOM,在其中一个子应用里用通过document api或jQuery根据id class获取dom时,要求只能获取当前应用下的DOM。

方案选型:

  1. Shadow DOM:缺点同上面的样式隔离。
  2. 重写子应用操作DOM方法:通过代理Document\Element原型链上的方法来实现把选择器的范围控制到当前子应用内,比如document.getElementById。

MicroApp

  • 重写子应用操作DOM方法。

Qiankun

  • 默认没有隔离。
  • 可选:严格样式隔离:Shadow DOM。

MicroApp、Qiankun 对比

框架 加载子应用机制 技术栈 支持多应用 样式隔离 JS沙箱隔离 元素DOM隔离
MicroApp single-spa 基于路由 多框架或无框架兼容 支持 css scope + css modules Proxy 重写操作DOM方法
Qiankun Web Components 多框架或无框架兼容 支持 动态切换样式表 + css modules Proxy 不支持

还有其它特性这里就不分析了,比如 资源预加载 数据通信 这些这俩框架都支持。

自定义微服务框架的技术选型

如果不用第三方的框架,想自己实现一个微服务框架,应该怎么实现呢?

技术选型推荐:

加载子应用机制 技术栈

感觉两种框架基本原理都一样,只是实现方式不同,一个用Web Components,另一个用方法,直接参考选一个就行。

样式隔离

  • Shadow DOM:有兼容问题,不建议。
  • 约定规范前缀:如果有定义子应用全局样式需求,可以使用,采用约定规范前缀,尽量安排专人控制好scope,不要乱用滥用。
  • css scope:需要写复杂逻辑,而且有些case需要做适配,不建议。
  • css modules:有webpack构建的都能用,建议使用。
    • 建议主应用common或layout样式用class name,方便子应用重写,其它用css modules

综合看,css modules是比较合适,也是成本最低的方案。如果更高级些,想兼容性高,可以支持css scope,参考MicroApp实现方式。

JS沙箱隔离

首选基于Proxy的沙箱机制。实现代码网上很多,或者直接用俩框架源码。

元素DOM隔离

建议不要用document api或jQuery获取DOM,所有业务都用ref方式获取DOM,或者个别可以严格控制DOM id和class。

或者参考MicroApp,重写子应用操作DOM方法。

问题

  1. 是否需要Web Components?

MicroApp用了WCs,但是它的好处是,无论主应用用的什么框架,React还是Vue,都可以直接在jsx\template里写<micro-app ,不用MicroApp自己还得维护每个框架一个组件,还得根据不同框架打包,而且只有一个组件,它只是一个壳子,一个定义子应用位置的壳子。

如果想自己实现一个微服务框架产品,自己用,那就根据自己产品技术栈实现一个对应控件就行了。比如用React,就对应一个React组件,实现类似<micro-app组件的效果。当然也可以用WCs定义,毕竟组件逻辑不太依赖框架,只是一个壳子。

  1. 公共控件是否需要Web Components?
  • 如果子应用都是同一个框架,比如React,那没必要用WCs,直接定义一套React框架的公共组件库就行。
  • 如果子应用可能是不同框架,比如有的React、有的Vue、有的是jQuery,那就需要定义一套WCs公共组件库。

总结

本文主要分析对比了 MicroAppQiankun 两大微服务框架,从各方面需求特性上分析每个框架的优缺点,每个微服务特性的方案的技术选型。最后如何根据自己的业务需求,选择适合自己的微服务框架,以及如何实现自己的微服务框架。

另外,Webpack5 的 Module Federation 联邦模块 也可以用来当做另一种微前端的解决方案,但是使用场景跟上面说的框架不一样,之后文章也会对这个技术做介绍,看看它解决了微前端哪些问题,又能做到上面框架哪些实现不了的事儿。

相关推荐
小白学前端66629 分钟前
React Router 深入指南:从入门到进阶
前端·react.js·react
言之。1 小时前
【面试题】构建高并发、高可用服务架构:技术选型与设计
架构
web130933203981 小时前
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
前端
outstanding木槿1 小时前
react+antd的Table组件编辑单元格
前端·javascript·react.js·前端框架
好名字08212 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
隐形喷火龙2 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
m0_748241122 小时前
Selenium之Web元素定位
前端·selenium·测试工具
风无雨2 小时前
react杂乱笔记(一)
前端·笔记·react.js
前端小魔女2 小时前
2024-我赚到自媒体第一桶金
前端·rust