基于下一代构建方案落地JOYY业务中台微前端

背景

目前通过一系列调研,大致总结出主流微前端方案大致分为前端

  • 基座模式:经过搭建基座、配置中心来管理子应用
    • 统一框架约定方案《微前端在美团外卖的实践背景》
      • 统一业务框架 REACT
      • 统一配置信息
      • 创建基座工程,用于管理子工程的路由切换、注册子工程的路由和全局Store层、提供全局库和复用层
    • 问题点
      • 经过中心化配置的方式注册到基座工程进行加载
      • 项目改造存在必定成本
      • 代码复用性以及子应用调用的易用性存在疑虑
    • 多框架并存方案Single-spa
      • 多框架并存、而且实现互不干扰
      • 建立根应用程序,以动态模块加载的方式加载子应用。
      • 独立发布的子应用提供一个活动 url 资源地址,随后在根应用中借助模块加载器(如 SystemJS)动态加载。
    • 问题点
      • 对于React 深度定制项目来讲,没法作到状态管理很好的传递
      • 对于非标准的AMD、UMD、SystemJS 等加载方式的库会存在依赖问题(须要针对性改造)
      • 多框架实现体积过大以及存在必定的调试成本
  • 自组织模式:经过约定进行互调
    • monorepo + npm包组合
    • amd,cmd or umd 等直接引用
    • webpack external
    • 问题点

思考

目前业务中台在业务推动过程当中遇到比较多的问题是webpack

  • 如何更好的减小代码冗余
  • 如何更高效的提高开发效率
  • 如何减小通用资源更新所带来的影响力度
  • 项目与项目之间如何更好下沉业务组件
  • 可复用库与组件之间如何造成约定类型或者文档,让调用方更加高效完成任务,减小沟通成本

统一技术栈

从开发初期咱们约定了中台的统一框架:React & hook + React-dom + React-router-dom + Mobx + Typescript,减小后期的额外框架消耗以及维护成本;
复用组件、工具库之间使用lerna + monorepo 方式下沉项目组件,经过npm方式安装到独立业务git

从项目过程当中遇到形形式式的包管理问题,以及代码重复打包,包信息更新不能及时等等问题github

尝试使用 single-spa 落地微前端

  • 项目推动中期上微前端须要对项目源码进行改造
  • 项目深度依赖mobx 进行状态管理,依赖react-router-dom 作路由管理,在通用组件调用的同时不能用路由包裹传递
  • 依赖single-spa 对非 umd 调用库支持不足须要进行必定改造

自组织模式

自组织模式:应用之间是平等的,不存在相互管理的模式。设计难度大,不方便实施,可是通用度高。
从目前主流开发模式下是很难完成 自组织模式的微前端落地,直到 Module Federation的出现web

方案设计

Module Federation 的特性中咱们挖掘出一套属于业务中台的设计模型

  • 组件联邦机制方式代替中心化,无需基站以及配置中心介入
  • 以ts类型的方式进行约定
  • 统一React框架、让组件中能够深度定制与引用(无需更改原有业务代码)
  • 创建完善脚手架和类型同步方案,让开发部署获得约束以及自动化完成

基站式微前端方案 VS EMP微前端方案

微前端对比

基站式微前端 EMP 微前端
路由 注册机制+子项目自定义 项目自定义,无需注册
支持多框架 支持 约定React框架(减小冗余与维护成本)
复用组件引用 沙箱方式 可共享状态组件方式
部署入口 基座 任何项目能够做为入口
Store 状态共享 需改造 无需改造、无需注册、直接调用
模块调用 部分须要进行改造 直接调用
配置中心 约定入口 无(独立入口或独立组件支持,无需配置)
Typescript类型提示 没法判断 提供一站式类型判断闭环
项目重构 须要根据约定重构 修改引用便可

EMP工做流

  • @efox/emp-cli 脚手架主要做用是
    • 调试
    • 构建、代码分析
    • 生成项目所需类型
    • 经过远程项目类型
  • @efox/emp-tune-dts-plugin ts相关类型操做
    • 1.在插件生命周期compiler.hooks.afterEmit.tap 执行生成类型文件
    • 2.类型文件生成后进行修正类型文件
  • @efox/emp-tsconfig 针对ts与微前端定制配置

用例代码展现

antd + react-router-dom 为例经过远程方式引入外部定义好的骨架应用npm

//base->App.tsx
const App = ({layout, routes, stores}: RouterCompType) => (
    <StoreProvider stores={stores}> <RouterComp layout={layout} routes={routes || []} /> </StoreProvider> ) 复制代码

当前应用引入外部库bootstrap

//app->bootstrap.tsx
import EMPApp from '@emp-antd/base/App'
import stores from 'src/stores'
const App = () => <EMPApp routes={routes} stores={stores} />
复制代码

远程同步ts类型代码提示antd

EMP基站设计模型

EMP基站主要做用是组织和共享通用库,而非统一入口、统一配置react-router

EMP基站设计模型
EMP基站设计模型

说明

框架级基站(以框架/技术栈为基础,为子基站提供框架级别的布局,方法,组件)

  • 项目级基站(以业务项目为基础,为项目提供业务组件,方法,路由,配置等)
    • 项目内容

优势:

  1. 支持多框架并存,而且实现互不干扰
  2. 可根据项目级别定义多层级别基站
  3. 项目级别基站相对独立
  4. 相同中台基站下的项目可快速开发移植
  5. 项目间可共享独立组件

EMP部署

多版本问题

在开发过程当中会遇到公共库的不断迭代以及项目使用的兼容性问题

  1. 基站部署:使用Docker的Volume方案,发布前,经过自定义Dockerfile,将每一个版本内容都放在Volume中,而后从Volume拉取数据,最后进行发布。
  2. Module Federationwebpack5 beta-17后支持定义版本,不一样入口能够应用能够定制本身的引用库版本如 React:16.13.1,而后从基站库相应版本里调用相应的组件

域名规范

域名规范遵循 emp-antd-[业务名称]-[环境].[一级域名].com。遵循这个规范,经过域名就能知道当前技术栈以及业务类型。

总结

从实战过程当中已经能够知足目前业务中台的微前端需求,调用以及协同方面也获得更好的推动

  • 一、从根本上摆脱了框架的束缚
  • 二、在最轻量级的基础上进行微前端化,而且大量保留了原来代码的业务逻辑
  • 三、最大化减小代码的冗余和更高的代码复用
  • 四、落地应用不受入口限制,大大的提高了应用的定制如多主题等诉求

做者


Ken.Xu

D.Ragon

Abel

Benny Shi

Jiguli
相关文章
相关标签/搜索