# 微前端(预研)

2020年4月,前期预研

WARNING

此文章是2020年4月,未投入生产时的调研报告,仅作为参考留档。

在实际的使用中,随着对微前端的探索的加深以及业务形态的清晰,微前端也在逐渐改进,请以最终呈现效果为准。

原文:微前端方案预研 - 语雀

# 参考链接

参考qiankun团队给出的微前端分析: 可能是你见过最完善的微前端解决方案

分析很到位,而且与我们的思路很契合

qiankun

# 基础设计

# 目录结构

├── core # 核心运行库
└── global-provider # 跨模块通信
1
2

# 包名

yarn add @h3yun/microfrontend

yarn add @h3yun/global-provider

1
2
3
4

# 第三方框架预研

可借鉴或可能使用的第三方框架

# single-spa

最原始最基础的微前端实现 https://single-spa.js.org/

# qiankun

阿里微前端解决方案,亮点:HTML Entry,JS 沙箱,基于Shadow DOM的样式隔离; https://qiankun.umijs.org

# SystemJS

可以在浏览器运行的动态模块加载器,支持ES6模块规范;在微前端中适合做公共模块的复用; https://github.com/systemjs/systemjs

# MobX

简单、独立的状态管理; https://cn.mobx.js.org/

# import-html-entry

qiankun的作者开发的用来加载HTML Entry的插件,有趣; https://github.com/kuitos/import-html-entry

# 沙箱

通过ES6的Proxy特性,拦截全局变量设置;  子应用之间,全局变量、事件在各个子应用内独立。

而且它实际实现了类似js原型链的继承机制,在子应用找不到全局值,会到父应用找。可以实现在主框架上加载umd模块;

局限性分析:需要抛弃IE浏览器;都氚云3.0了,还考虑什么IE!?

TIP

结论:好东西,必用!

# 集成方式

  • [ ] 构建时加载
  • [x] 运行时加载

组内建议运行时加载,WL建议构建时加载。但我们坚持运行时加载。 原因:构建时加载,又回到了原始的基于构建集成的开发模式,没有做到真正的独立。而且会导致代码与构建过程或构建工具耦合。WL担心的“运行时加载,容易得不到测试的问题”,会有其他的手段解决。

参考qiankun团队的分析:

image.png

TIP

结论: 运行时加载, 必用!

# App Entry

  • [ ] JS Entry
  • [x] HTML Entry

通过fetch获取html内容,直接插入到浏览器DOM中渲染。可使用import-html-entry库来加载; 而且可以做到一定的样式隔离作用;

局限性分析:HTMLEntry 需要多一次请求来拉取html内容

参考qiankun团队的分析: image.png

TIP

结论: HTML Entry 好东西,必用!

在实际应用中,也会发现HTML Entry的一些问题,后文会提到

# 样式隔离

有以下两种方案:

  • [ ] Shadow dom方案
  • [x] 人为规范及约定,BEM / CSS Modules

其次,上文提到,HTML Entry的加载方式有一定样式隔离作用;

Shadow DOM是好东西,但是只用来做样式隔离,还存在一些问题:

  1. 无法抽离公共样式,真的就完全隔离了,无法灵活处理;
  2. 一些对外部节点的处理的兼容。比如 sub-app 里调用了 antd modal 组件,由于 modal 是动态挂载到 document.body 的,而由于 Shadow DOM 的特性 antd 的样式只会在 shadow 这个作用域下生效,结果就是弹出框无法应用到 antd 的样式。

但是人为的约定和规范也不是最佳方案,所以这个问题没有最优解,只有权衡;

结论:Shadow DOM 利弊权衡之下,选择人为规范;继续关注研究其他方案;

# 跨模块通信

开放两种跨模块通信机制:

# 全局状态管理(GlobalState)

基于MobX实现

# 全局事件管理(EventBus)

中规中矩的eventbus

详细介绍请看:跨模块解决方案

# 公共依赖的处理

# 加载方式

对于公共依赖的处理,无非以下三种方案;

# npm模块加载

通过npm模块引入; 优点是依赖加载更合理,并可配置按需加载, 缺点是子应用之间,重复的模块打包会有重复;

# 外部cdn加载

将依赖打包成umd模块,通过外部cdn加载进来; 优点是抽离公共代码,减少重复; 缺点是会影响首屏加载资源,可能会出现多余的代码;

# import-maps规范

使用SystemJS库,实现遵循import-maps规范的加载方式; 优点是可以完全自定义化加载,标准规范的加载方式;依赖可复用,可按需加载,可发布外部cdn; 缺点是对SystemJS库的依赖,以及文件的碎片化,没有捆绑加载也不是件好事;

# 加载策略

# 基础框架采用外部cdn加载

vuevuexvue-routerlodashsingle-spa等基础框架采用外部cdn加载

# 组件库采用npm模块加载

以下组件库保持在npm中按需加载

  • lodash
  • @h3/antd-vue
  • @h3/awesome-ui
  • @h3yun-shared/packages
  • @h3yun-shared/utils
  • @h3yun-shared/library
  • @h3yun-shared/const

# 复合组件import-maps加载

复合组件调用SystemJS加载

# 项目模板

模板是用于快速创建项目使用,集成于脚手架和技术管理平台中; 四种模板:

模板领域 模板名字
主框架模板 spa-root-template
子应用模板 spa-module-template
复合组件模板 spa-package-template

# 静态库管理(static-library)

(未完待续)

以下是新版本处理方案

# 框架类

bundle模块名 内部模块 描述
bundle vue, vuex, vue-router, axios,vue-class-component,
vue-property-decorator 氚云基础框架,捆绑vue生态及axios加载器
vuebundle vue, vuex, vue-router vue框架
h3yun-spa @h3yun-spa/core,

@h3yun-spa/global-provider, single-spa, SystemJS | 微前端主框架依赖库 |

# 工具类

bundle模块名 内部模块 描述
moment moment moment库
sentry sentry/brower, sentry/intergrations sentry异常日志系统SDK
jquery jquery jquery库,用于氚云2.0,3.0不考虑
bootstrap bootstrap bootstrap库,用于氚云2.0,3.0不考虑

# 公共业务组件库

详见:模块拆分

# 参考链接

micro-frontends 可能是你见过最完善的微前端解决方案 import-maps