专栏名称: 互联网侦察
最懂你的程序员在这里,我们不仅聊技术,我们还聊情感,聊人生。
目录
相关文章推荐
Linux就该这么学  ·  国企也中招!官网被挂上 “ ... ·  16 小时前  
Linux就该这么学  ·  运维老鸟私藏的 100 ... ·  2 天前  
Linux就该这么学  ·  开源办公套件 LibreOffice ... ·  2 天前  
Linux就该这么学  ·  美女博主爆改 家用空调外机 ... ·  2 天前  
51好读  ›  专栏  ›  互联网侦察

微前端在小米 CRM 系统的实践

互联网侦察  · 公众号  ·  · 2020-06-15 08:08

正文

作者:木子朗

https://www.lishuaishuai.com/architecture/1344.html

大型组织的组织结构、软件架构在不断地发生变化。移动优先(Mobile First)、App中台(One App)、中台战略等,各种口号在不断的提出、修改和演进。同时,业务也在不断地发展,导致应用不断膨胀,进一步映射到软件架构上。
现有Web应用(SPA)不能很好的拓展和部署,随着时间的推移,各个项目变得越来越臃肿,web应用变得越来越难以维护。
微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用还可以独立运行、独立开发、独立部署。
Techniques, strategies and recipes for building a modern web app with multiple teams that can ship features independently. — Micro Frontends

实施微前端的六种方式

《前端架构从入门到微前端》一书中,将微前端的实施分为六种:

路由分发
路由分发式微前端,即通过路由将不同的业务分发到不同的、独立前端应用上。其通常可以通过 HTTP 服务器的反向代理来实现,又或者是应用框架自带的路由来解决。如图:
前端微服务化
前端微服务化,是微服务架构在前端的实施,每个前端应用都是完全独立(技术栈、开发、部署、构建独立)、自主运行的,最后通过模块化的方式组合出完成的应用。
采用这种方式意味着,一个页面上可以同时存在两个以上的前端应用在运行。如图:
目前主流的框架有 Single-SPA、qiankun、Mooa,后两者都是基于 Single-SPA 的封装。
微应用
微应用化是指在开发时应用都是以单一、微小应用的形式存在的,而在运行时,则是通过构建系统合并这些应用,并组合成一个新的应用。
微应用化大都是以软件工程的方式来完成前端应用的聚合,因此又可以称之为组合式集成。
微应用化只能使用唯一的一种前端框架。
如图:
微件化
微件化(Widget)是一段可以直接嵌入应用上运行的代码,它由开发人员预先编译好,在加载时不需要再做任何修改或编译。微前端下的微件化是指,每个业务团第编写自己的业务代码,并将编译好的代码部署到指定的服务器上,运行时只需要加载指定的代码即可。
如图:
iframe
iFrame 作为一个非常古老的,人人都觉得普通的技术,却一直很管用。
HTML 内联框架元素 表示嵌套的正在浏览的上下文,能有效地将另一个 HTML 页面嵌入到当前页面中。
iframe 可以创建一个全新的独立的宿主环境,这意味着我们的前端应用之间可以相互独立运行。采用 iframe 有几个重要的前提:
  • 网站不需要 SEO 支持

  • 拥有相应的应用管理机制。

在很多业务场景下,难免会遇到一些难以解决的问题,那么可以引入 iframe 来解决。
Web Components
Web Components 是一套不同的技术,允许开发者创建可重用的定制元素(它们的功能封装在代码之外)并且在您 Web 应用中使用它们。
在真正的项目上使用 Web Components技术,离现在还有一些距离,结合 Web Components 来构建前端应用,是一种面向未来演进的架构。或者说在未来可以采用这种方式来构建应用。
如图:
在真实的业务场景中,往往是上面提到六种方式中的几种的结合使用,或者是某种方式的变种。下面看我遇到的真实场景。

真实的业务场景

现有三个内部系统,下面称之为 old-a、old-b和C,其中,old-a和old-b是老旧的前后端未分离项目,C为前后端分离的SPA应用(React + HIUI),三个系统的架构图大致如下:
可以看到,old-a 运行在一台服务器1上,old-b运行在服务器2上,C系统的前端资源在服务器2上,并且C没有自己的域名。
三个系统均在后端同学维护和开发,他们的需求如下:
  • 统一的域名

  • 统一的界面和交互

  • 系统需要方便拓展

  • 不希望开发阶段每个系统有独立的代码仓库

  • CI 构建

怎么改造?

关键点
考虑开发同学的需求和开发成本、维护成本、未来的可拓展性,系统改造关键点如下:
  • 申请统一的域名(暂且称之为crm.mi.com)

  • 将 old-a 和 old-b 两个老旧的系统样式调整,像系统C靠拢

  • 三个系统使用统一的菜单和权限

  • 三个系统使用统一的 SSO

  • C 系统和正在开发的 X 个系统使用 CI 解决打包和手动 copy 的问题

微前端几种方式对比
总体的改造方案使用微前端的思想进行。对上面提到的六种方式进行对比(点击查看大图):
实施
对于上面几种方式,在具体的实施使用了路由分发、iFrame、应用微服务化、微应用化的融合方式。或者说是某种方案的变种,因为改造之后同时具备了这几种方案的特点。
对于C系统和正在开发的x个系统使用 single-spa 做改造,对于老旧的系统 old-a 和 old-b 使用 iframe 接入。
改造后如下图:
此时,两个老系统分别部署在各自的服务器,C 和未来的多个应用部署在同一台服务器。然后,在 Nginx 层 为老系统分配了两个路由(暂且称之为 old-a 和old-b),分别将请求打到各自的服务器,根路由打到 C 和 xx 应用的服务器。
使用React 框架的 C 和 xx 应用基于 single-spa 改造后,那么老系统 iframe 如何接入?
在配置菜单时,老系统路由会被带上标识,统一交给其中一个应用以 iframe 的方式处理。
如图:
改造后微前端架构图:

一些问题

子应用注册方式
官方示例:
  1. // single-spa-config.js

  2. import{ registerApplication, start } from'single-spa'


  3. registerApplication("applicationName", loadingFunction, activityFunction)

  4. start()


  5. function loadingFunction() {

  6. returnimport("src/app1/main.js")

  7. }

  8. function activityFunction(location) {

  9. return location.pathname.indexOf("/app1/") === 0

  10. }

当增加一个应用的时候,就需要对 single-spa-config.js 文件进行修改。
通过可配置的方式实现子应用注册:
  1. // single-spa-config.js

  2. import* as singleSpa from'single-spa'

  3. import config from'./manifest.json'


  4. registerApp(config)


  5. singleSpa.start()


  6. function registerApp(conf) {

  7. conf.forEach(application => {

  8. singleSpa.registerApplication(

  9. application.name,

  10. () => import(`./${application.name}.app/index.js`),

  11. pathPrefix(application.activeRule, application.strict),

  12. )

  13. })

  14. }


  15. function pathPrefix(prefix, strict) {

  16. returnfunction (location) {

  17. if(strict) {

  18. return location.pathname === prefix

  19. }

  20. return location.pathname.startsWith(`${prefix}`)

  21. }

  22. }

  1. // manifest.json

  2. [

  3. {

  4. "name": "layout",

  5. "activeRule": "/"

  6. },

  7. {

  8. "name": "welcome",

  9. "activeRule": "/" ,

  10. "strict": true

  11. },

  12. {

  13. "name": "iframe",

  14. "activeRule": "/link"

  15. },

  16. {

  17. "name": "app1",

  18. "activeRule": "/app1"

  19. },

  20. {

  21. "name": "app2",

  22. "activeRule": "/app2"

  23. }

  24. ]

共享cookie
将域名统一的一大好处是 iframe 域名和主应用域名同源。没有了跨域 可以在 layout 统一 SSO 登录,通过 cookie 共享让其他模块拿到登录信息。
应用之间数据共享及通信
由于此次改造,应用之间不涉及数据共享,所以没有顶级 store 的概念。模块之间的简单通信 可以通过 postMessage 或基于浏览器原生事件做通信。
  1. // 应用 A







请到「今天看啥」查看全文