为什么我们在 BuzzFeed 使用微前端

2025-06-08

为什么我们在 BuzzFeed 使用微前端

关于“微前端”的定义或许尚未达成共识。DAZN 的聪明人认为它是一系列由客户端编排器管理的完整页面。其他方法,例如OpenComponents,则由多个微前端组成单个页面。

BuzzFeed 的用例介于两者之间。我不会说我们拥有微前端架构;但是,我们确实在页面的某些部分利用了它们。如果 API 返回的是完整渲染的 HTML(和资源),但没有<html>or<body>元素,我们就认为它是微前端。

我们有三个微前端:标题组件、文章内容和交互式嵌入。它们都采用了微前端方法,因为它们代表了真实且独特的业务问题。

微前端 #1:标题

为什么?组件分发

Buzzfeed.com 标题图片

这是 buzzfeed.com 的头部信息。它包含一层轻量级的配置以及合理的代码量:这足以让它值得抽象出来,而不是在我们所有的服务中重复使用。

最初,我们进行了抽象,并将其提取到 npm 包中,服务在构建过程中导入这些包。这样一来,我们就可以消除重复,同时让服务将头文件作为其自身构建过程的一部分进行打包(这意味着我们可以轻松地删除重复的通用代码和库)。

在只有两三个服务的情况下,这种技术效果很好,但 buzzfeed.com 背后有十多个渲染服务。这意味着每次我们想要修改 header 时,都必须进行以下十多次修改:

  • 更新标题中的代码
  • 发起拉取请求
  • 合并并发布到 npm
  • 更新服务 package.json
  • 发起拉取请求
  • 合并并部署服务

这变得极其耗时,导致团队因此避免修改 header。当然,我们可以通过一些方法改进这个工作流程(例如,使用松散语义版本控制 (loose semver),只需重新构建服务,自动更新和创建服务 PR),但这些方法仍然感觉不对。通过迁移到微前端模式,我们现在能够将 header 即时分发到所有服务,并且在 buzzfeed.com 上更新 header 的工作流程现在是:

  • 更新标题中的代码
  • 发起拉取请求
  • 部署标头

微前端 #2:发布内容(或者我们称之为:Subbuzzes)

为什么?为了与CMS保持合同

我们的内容有多个不同的“目的地”(例如 BuzzFeed 和 BuzzFeed News),但每个目的地都由同一个 CMS 提供支持。每个目的地都有自己的服务(或多个服务),连接到我们的内容 API。这意味着我们有能力在多个目的地渲染相同的内容;然而,实际上我们选择不这样做。

相同的内容在三个不同的 BuzzFeed 目的地呈现。

这也意味着我们必须在 CMS / 内容 API 和渲染服务之间维护一个契约。为了更容易理解,我们来举个例子。

当编辑者想要在页面中添加图片时,他们会在 CMS 中选择图片“subbuzz”并上传。然后,他们可以选择为该图片添加扩展。其中一项扩展功能是将图片标记为显示“图片内容”。添加此扩展的目的是使图片模糊化,用户必须选择启用才能查看(这对于敏感新闻内容尤为重要)。然而,就 CMS 而言,这仅仅意味着存储在图片上的一个布尔值。由于 CMS 依赖于渲染服务来添加模糊叠加层,因此最终导致两者之间存在隐式耦合。如果目标平台不支持此功能,那么用户将会看到图片内容,我们也未能实现编辑者的意图。

那么这与微前端有什么关系?

我们可以选择将这些 subbuzz 模板抽象成一个 npm 包,并在各个目标之间共享;但是,当我们更改 CMS 中某些内容的支持时,我们需要渲染服务能够立即反映出来。CMS 部署时没有版本控制,内容 API 只公开主版本号。如果使用语义化版本 (semver) 将这些 subbuzz 与 npm 包耦合,并通过包进行部署,它们很难保持同步。通过将 subbuzz 移到 HTTP API 后面,我们可以立即更新所有目标上的渲染-cms 契约,并确保每个目标都支持最新的 CMS 功能。

微前端 #3:嵌入(Buzz Format 平台)

为什么?独立于平台

微前端最清晰的用例或许是:嵌入。我们托管了大量的嵌入内容(Instagram、Twitter 等),包括第一方嵌入。我们称之为 BFP,即 Buzz Format Platform(Buzz 格式平台),它们可以是任何内容,从新闻通讯注册到高度可复用的测验格式,再到支持调查报道的定制格式。

嵌入的入口点通常是 iframe 或 script 元素,因此它本身并不算微前端。我们尽可能打破这种模式,将它们渲染到服务器端,并将返回的 DOM 直接包含在页面中。这样做是为了能够以分布式格式(例如我们的 BuzzFeed 移动应用或 Facebook 即时文章)渲染嵌入内容,并将内容暴露给搜索引擎爬虫。

BFP 提供了平台独立性,让工程师感觉就像在开发一个小组件,而不必考虑更广泛的 BuzzFeed 生态系统。我们在创建开发者环境时一直努力实现这种感觉,而微前端无疑提供了这种机会。

权衡

微前端架构可以带来出色的开发体验和极大的灵活性,但它们并非免费。您需要权衡以下几点:

更大的客户端资产或更严格的编排

我们在浏览器中构建微前端,这意味着没有单一的构建流程可以优化和删除共享依赖项的重复数据。要在浏览器级别实现这一点,您需要对所有依赖项进行代码拆分,并确保使用相同的版本——或者在编排层中进行构建。

发布更新时风险更高

正如我们能够即时将新的变更分发到多个服务一样,我们也能够分发错误和错误。这些错误在运行时出现,而不是在构建时或持续集成 (CI) 中。我们将这种风险的增加视为一个契机,以便更加专注于测试并确保组件契约得到维护。

也有人批评微前端难以打造统一的用户体验,但我们从未遇到过这种情况。所有这些微前端都通过共享包继承了设计模式和较小的组件。

总体而言,微前端模式在 BuzzFeed Tech 的这些用例中效果良好,并且在过去一两年中得到了充分的测试。肯定会有一个拐点,当拥有更多微前端时,需要做更多工作来抵消第一个权衡,但我们认为我们还没有到达那个拐点,也不预计很快就会到达——将组件抽象到共享包中对于我们大多数用例来说效果很好。如果情况并非如此,那么最好有另一种架构模式可供选择。

鏂囩珷鏉ユ簮锛�https://dev.to/buzzfeedtech/why-we-use-micro-frontends-at-buzzfeed-1k9o
PREV
开发者品牌建设:实用指南
NEXT
使用 Mochawesome Reporter 和 Cypress Execution