对微前端的11个错误认识

2020 年 10 月 11 日

对微前端的11个错误认识

本文最初发布于 Bits and Pieces 博客,经原作者授权由 InfoQ 中文站翻译并分享。

微前端是一个可以追溯到多年前的新趋势。随着新方法的出现以及各种挑战被克服,它们正在慢慢地进入主流。但遗憾的是,许多非常明显的认识误区,让许多人很难理解微前端到底是什么。

简而言之,微前端就是将微服务的一些好处引入前端。除此之外,我们不应该忘记,微服务也不是什么“银弹”。

提示:要在微前端或任何其他项目之间共享 React/Angular/Vue 组件,可以使用像 Bit 这样的工具。它允许你从任何代码库中“harvest”组件,并将它们共享到 bit.dev 的一个集合中。它让团队可以在任何存储库中使用你的组件。使用它可以优化协作、加速开发和保持 UI 一致性。

示例:在 bit.dev 中查找共享 React 组件

认识误区

我想列一下在过去几个月中,我最常听到的关于微前端的误解。先从从一个明显的例子开始。

微前端需要 JavaScript

目前,许多微前端解决方案都是 JavaScript 框架。这怎么可能错呢?JavaScript 不再是可选的。每个人都想要高度交互的体验,而 JS 在提供这些体验中发挥着至关重要的作用。

除了加载速度快、可访问 Web 应用的优点外,还有其他因素应该考虑。因此,许多 JavaScript 框架都提供了 isomorphic 渲染能力。最终,这让它们不仅能够在客户端进行拼接(stitch),还能在服务器上准备好一切。如果有性能要求(如第一次有意义渲染的初始时间),这个选项听起来很不错。

请记住,isomorphic 渲染有其自身的挑战。

然而,即使一个 JavaScript 解决方案没有提供 isomorphic 呈现,这也没什么问题。如果不想在构建微前端时使用 JavaScript,我们当然可以这样做。有许多模式,其中很多根本不需要 JavaScript。

考虑一种“比较旧的”模式:使用<frameset>。我听见你笑了?好吧,有一些现如今人们试图做的分割,它以前就支持了(下文有更详细的讨论)。一个页面(可能由另一个服务渲染)负责菜单,而另一个页面负责标题。

复制代码
<frameset cols="25%,*,25%">
<frame src="menu.html">
<frame src="content.html">
<frame src="sidebar.html">
</frameset>

如今,我们使用更灵活(且仍然受到活跃支持)的<iframe>元素。它们提供了一些很好的特性——最重要的是使得不同的微前端相互隔离,但仍然可以通过postMessage进行通信。

微前端只在客户端有效

在 JavaScript 认识误区之后,这是下一个层次。当然,在客户端有多种技术可以实现微前端,实际上,我们甚至不需要<iframe>或任何类似的技术。

微前端可以像服务器端“includes”一样简单。有了诸如 Edge Side Includes 之类的高级技术,这将变得更加强大。如果我们排除了在微前端功能中实现的微前端场景,那么即使是简单的链接也可以很好的工作。最终,微前端解决方案也能像小而独立的服务器端渲染器一样简单。每个渲染器可能只有一个页面那么小。

下图展示了在反向代理中发生的更高级的拼接:

通过反向代理实现服务器端拼接

当然,可能 JavaScript 有许多优点,但它仍然高度依赖于你试图通过微前端解决的问题。根据你的需要,服务器端解决方案可能仍然是最好的(或者至少是更好的)选择。

你应该使用多个框架

在几乎每一个关于微前端的教程中,不同的部分不仅由不同的团队开发,而且使用了不同的技术。这是假的。

适当的微前端方法可能使用不同的技术,但是,这不应该是目标。我们做微服务也不只是为了在后端拼凑技术。如果我们使用多种技术,那只是因为我们获得了一个特定的好处。

我们的目标应该始终是某种统一性。最好的方法是考虑一个新项目:我们会怎么做?如果答案是“使用单一框架”,那么我们就走上正轨了。

长远来看,有很多原因可以解释为什么应用程序中会出现多个框架。可能是遗留的,可能为了方便,也可能是一个概念验证。无论是什么原因:能够处理这种场景还是不错的,但它绝不应该是开始就希望达到的状态。

不管你的微前端框架多高效——使用多个框架总是要付出不可忽视的代价。不仅初始渲染会花费更长的时间,而且内存消耗也会朝着错误的方向发展。不能使用方便模型(例如,针对某个框架的模式库)。需要更多的重复。最终,程序的 Bug 数量、不一致行为和可感知的响应性都会受到影响。

按技术组件划分

一般来说,这没有多大意义。我还没见过微服务后端的数据处理在一个服务中而 API 在另一个服务中。通常,服务由多个层组成。虽然某些技术内容(如日志记录)肯定会引入到公共服务中,但有时也会使用诸如 Sidecar 之类的技术。此外,还需要通用服务编程技术。

对于微前端,情况也是如此。为什么一个微前端只能做菜单?每个微前端都有相应的菜单吗?拆分应该根据业务需求来做,而不是技术决策。如果你读过一些关于领域驱动设计的书,你就会知道它是关于定义这些领域的——而这个定义与任何技术要求无关。

考虑以下划分:

按布局分解成微前端

这些都是技术组件,和微前端无关。在一个真实的微前端应用程序中,屏幕可能看起来是这样的。

按领域分解成微前端

的确,这里的拼接要复杂得多,但这是一个可靠的微前端应用程序应该为你提供的!

不应该共享任何东西

不。你应该共享那些值得共享的东西。你绝对不应该共享所有东西(见下一条)。但要做到始终如一,你至少需要共享一套原则。至于是通过共享库、共享 URL,或者只是在构建或设计应用程序时使用的文档,那就不重要了。

对于微服务,“无共享”架构如下图所示:

微服务的“无共享”架构

在浏览器中,这将导致使用<iframe>,因为目前没有其他方法可以防止资源泄漏。使用影子 DOM,则 CSS 可能会被隔离,但脚本层面仍然能访问所有内容。

即使想遵循无共享的架构,我们也会遇到麻烦。

当然,共享的程度越深(例如,使用一个通过应用 shell 追加到 DOM 的共享库),就越会出问题。另一方面,共享程度越浅(例如,只是一个指定基本设计元素的文档),就会出现更多的不一致性。

应该共享一切

绝对不是。如果这样想,那么单体更有意义。就性能而言,这可能已经是一个问题了。什么可以延迟加载?我们能去掉一些东西吗?但真正的问题是依赖管理。什么都不能更新,因为它可能会破坏某个东西。

共享部件的好处是一致性保证。

现在,如果我们共享所有的东西,我们就是用复杂性来换一致性。这种一致性是不可维护的,因为复杂性会在每个角落引入 Bug。

问题的根源在于“依赖地狱”。下图很好地说明了这一点。

简而言之,如果一切都相互依赖,那么我们就会有依赖问题。仅仅更新一个方框就会影响整个系统。一致吗?确实。简单的?绝不。

微前端只是 Web 端的

为什么只是 Web?诚然,到目前为止,我们接触到的主要是 Web,但其概念和想法可以应用于任何类型的应用程序(移动应用、客户端应用……甚至是 CLI 工具)。在我看来,微前端只是“插件架构”的一个花哨叫法。不过,插件接口如何设计,以及运行使用插件的应用程序需要具备什么条件,这就是另外一回事了。

下图显示了一个非常通用的插件架构,来自 Omar Elgabry

通用插件架构

该架构并没有在哪里运行的概念。它既可以在手机上运行,也能在 Windows 上运行,甚至还能在服务器上运行。

微前端需要大型团队

为什么?如果解决方案超级复杂,那么我肯定会找一个简单的。有些问题需要复杂的解决方案,但好的解决方案通常是简单的。

根据场景的不同,它甚至可能不需要一个分布式团队。拥有分布式团队是采用微前端的首要原因之一,但这不是唯一原因。另一个很好的理由是特性的粒度。

如果从业务的角度来看微前端,那么你就会发现,拥有启用和关闭特定特性的能力是很有意义的。针对不同的市场,使用不同的微前端。回到一个简单的权限模式,这是有意义的。不需要编写代码来根据特定条件打开或关闭某些东西。所有这些都留给公共层,可以根据(可能是动态的)条件激活或停用。

这样,不能(或不应该)使用的代码也不会被交付。虽然这不应该是一个保护层,但它肯定是一个便捷(和性能)层。用户不会感到困惑,因为他们看到的是他们能做的。他们看不到没有交付的功能,所以没有字节浪费在不可用的代码上。

微前端无法调试

对于任何类型的实现(或供讨论的底层架构),开发经验都可能遭到削弱。应对这种情况的唯一方法是开发人员优先。实现中的第一原则应该是:使调试和开发成为可能。采用标准的工具。

有些微前端框架根本不接受这一点。有些需要在线连接、专用环境、多重服务……这不应该是标准,也绝不是常态。

微服务需要微前端(或反过来)

解耦的模块化后端可能为解耦前端打下了一个很好的基础,但通常情况下,情况并非如此。后端单体,前端模块化,也是完全可行的,例如,为简化个性化可能就要结合授权、权限和市场。

实际上,同样,微服务后端并不能证明适合将类似的模式应用于前端。许多微服务后端都是由单用途的应用程序操作的,它们的功能没有增加,只是外观发生了改变。

微前端需要单存储库

我已经读到过好几次,要创建一个微前端解决方案,就需要利用单存储库,最好使用像 Lerna 这样的工具。我不认可这一点。当然,单存储库有一些优点,但也有明显的缺点。

虽然有一些微前端框架需要联合 CI/CD 构建,但大多数都不需要。联合 CI/CD 构建通常会导致单存储库,因为其设置要简单得多。但对我来说,这是单体重新打包。如果你在单存储库上进行联合构建,那么你就失去了让微前端富有吸引力的两个非常重要的优点:

  1. 独立部署
  2. 独立开发

不管怎样,如果你看到微前端解决方案需要单存储库:那样做就行。一个精心设计的单体系统可能会更好,它不会有分布式系统的所有问题。

结论

微前端技术并不适合所有人。我不认为微前端是未来的发展趋势,但我也相信它们在未来会发挥重要作用。

原文链接:

https://blog.bitsrc.io/11-popular-misconceptions-about-micro-frontends-d5daecc92efb

2020 年 10 月 11 日 09:00 1628
用户头像

发布了 297 篇内容, 共 131.9 次阅读, 收获喜欢 582 次。

关注

评论 1 条评论

发布
用户头像
赞~感同身受
2020 年 10 月 12 日 14:21
回复
没有更多评论了
发现更多内容

《零基础学 Java》 FAQ 之 7-Java 中的内存是怎么分配的

臧萌

Java JVM

Mac 使用笔记

FeiLong

Android | Tangram动态页面之路(二)介绍

哈利迪

android

如果你觉得学习 Git 很枯燥,那是因为你还没玩过这款游戏!

GitHubDaily

git GitHub 编程 程序员 开发者工具

《后浪》产品经理篇(恶搞版)

静陌

产品经理 后浪

设计模式之观察者模式

设计模式

一文带你看清HTTP所有概念

cxuan

HTTP

松哥手把手教你定制 Spring Security 中的表单登录

江南一点雨

Java spring Spring Boot spring security

游戏夜读 | Scikit-learn迎来0.21之前

game1night

尽管HTTP/3已经来了,HTTP/2也得了解啊

清远

网络协议 HTTP

如何在一台计算机上安装多个 JDK 版本

mghio

Java jdk 版本管理工具

Harbor 2.0的飞跃: OCI 兼容的工件仓库

亨利笔记

Kubernetes 容器 k8s Harbor 镜像

Rust 与区块链四月月刊

Aimee 阿敏

区块链 rust 加密货币 crypto

从一次排查ES线上问题得出的总结——熔断机制

罗琦

elasticsearch 源码分析 circuit break 熔断

更聪明地学习,而不是苦读——《如何高效学习》

mzlogin

高效学习

Java新技术:封闭类

范学雷

Java 架构 编程语言

谈谈控制感(5):怎么破控制感损失的局

史方远

职场 心理 成长

松哥手把手带你入门 Spring Security,别再问密码怎么解密了

江南一点雨

Java spring Spring Boot spring security

Redis稳定性实践

心平气和

redis 缓存 稳定性

Python 核心技术与进阶 list & tuple

Bonaparte

Python3.6.1官方文档练习——初入江湖(二)

Sicolas Flamel

到底应不应该听父母的建议

Guanngxu

面试官:小伙子,听说你看过ThreadLocal源码?(万字图文深度解析ThreadLocal)

一枝花算不算浪漫

源码 并发编程 ThreadLocal

严选合伙人(二)

Neco.W

创业 重新理解创业 合伙人

回“疫”录(18):536公里的路

小天同学

疫情 回忆录 现实纪录 纪实 返程

聊聊我对技术一些性质的认识

Tanzv

技术 思考 新人

MySQL常用权限说明

一个有志气的DB

MySQL 用户研究

Xtrabackup的安装使用

一个有志气的DB

MySQL 工具 数据的分片和备份

对于程序员,那些既陌生又熟悉的计算机硬件

架构师修行之路

微软 编程 程序员 cpu 架构师

让你高效工作与学习的免费工具(1)

石云升

高效工作 效率工具 工具

业余前端的日常

顿晓

学习方法 前端 日常 专家 知识体系

对微前端的11个错误认识-InfoQ