Vercel 是一个 专为前端 开发者提供一体化平台,简化 Web 应用程序的构建和部署流程的公司。
除此之外,Vercel 团队还开源了很多知名前端框架,比如:Next.js。所以这是一个典型的由众多技术大佬组成的团队。
差点跑偏了,咱们回到今天内容的主题!
在上周,Vercel 团队公布了他们内部的【微前端设计方案】,所以咱们今天就来看看,这种头部技术团队,如何构建微前端方案的!
Vercel 如何采用微前端
官方团队原文:https://vercel.com/blog/how-vercel-adopted-microfrontends
Vercel 的主网站曾是一体化的 Next.js 大型应用,既服务于普通访客,也涵盖登录用户的仪表板。然而,随着 Vercel 的快速扩展,这种架构逐渐暴露出效率瓶颈:构建时间延长、依赖管理复杂化、工作流程频繁卡顿。哪怕是微小的变更,都需要重新构建整个应用,延缓了独立开发的进度,也影响了 CI 管道的运行效率。
于是,我们意识到:是时候进行架构变革了。
我们重新设计了架构,转向垂直微前端,从而简化了开发体验,缩短了预览构建时间和本地开发编译时间——提升超过 40%。通过删除非必要的微前端代码,我们不仅减少了依赖的体积,还大幅降低了页面加载时间,从而优化了用户性能。此举使得核心 Web 指标,如最大内容绘制 (LCP) 和 下一次绘制交互 (INP) 等都有了显著提升。
在 Vercel 对微前端支持的基础上,这一重大调整极大地改善了开发人员体验 (DX),同时也为进一步优化提供了清晰的方向。通过此次内部大规模迁移测试,我们为平台开发找到了更高效的流程。这篇博客不仅记录了我们的转型历程,也展示了我们为开发者简化流程、加速构建的实践。今后,我们将持续提升单个应用程序的构建速度,在保障用户性能的前提下,实现更优越的开发体验 (DX)。
接下来,让我们深入探讨这次转型的具体方法。
利用 Turbo
我们的第一步是着力改善 本地编译、构建时间 和 CI 工作流程。借助 Turborepo 支持的 Vercel monorepo,我们能够利用 Vercel Remote Cache 等功能,在 CI 管道中智能执行受影响的任务,大幅度减少了冗余操作。同时,我们引入了 Turbopack,极大提升了本地开发的速度。
然而,在推进这些优化的过程中,我们意识到:单一应用模式 对当前的 Vercel.com 已不再必要。通过应用内逻辑拆分,我们能够避免构建和编译中的无效工作,为开发人员带来更显著的速度提升。
水平和垂直微前端的选择
为了进一步提升效率,我们引入了微前端架构,将大型应用分解为更小、更独立的单元,支持跨产品领域和工程团队的并行开发。微前端架构的主要分割策略包括:
- 垂直微前端:按路径拆分,即每个页面由单个应用管理。这种方式清晰而高效,适合具有独立页面逻辑的场景,确保每个页面的开发与构建相对独立。
- 水平微前端:按功能拆分,多个应用同时在一个页面上运行。这种方式更适合需要在单页内加载不同功能模块的复杂应用场景。
图片
微前端的两种常见方法:单个页面内的多个微前端(水平分割)或使用单个微前端管理整个页面(垂直分割)。
每种微前端方法各有优缺点,根据具体用例都能带来实质性好处。正如 Luca Mezzalira 在其微前端专著中所述,垂直和水平分割的选择应依据项目需求权衡。
垂直分割 提供了良好的内聚力,但在切换不同微前端应用时可能带来导航挑战。虽然预取技术和 Chromium 的推测 API 可以缓解这一问题,但它们往往会增加资源使用,并受限于浏览器支持。
相比之下,水平分割 在同一页面上运行多个微前端模块,使得测试、发布、监控和调试更复杂,增加了运维管理难度。
我们最终选择了 垂直微前端,将应用拆分为用户少访问的逻辑部分,以减少构建时间和依赖复杂度,同时保留了单一存储库的统一性。早期测试结果显示,这种方法将构建时间缩短了 50%,并在开发与生产中简化了模块所有权,使开发人员能够享受到单一应用的流畅体验。
我们的迁移路径
接下来,我们将单体前端应用迁移到更小的垂直应用中,以确保开发和用户体验不受影响。具体来说,我们将应用划分为三个核心区域:
- 营销
- 文档
- 登录仪表板
这些区域在功能和用户界面上各自独立,用户不常在它们之间切换,因此非常适合分离。
图片
用户在单个微前端内体验软导航,在微前端之间移动时体验硬导航
借助 Next.js 的 Multi-Zones 功能,我们可以无缝支持垂直微前端架构。为了控制迁移风险,我们选择增量迁移,创建全新的应用而非分叉原始代码库。虽然分叉看似简单,但它会带来复杂的同步和一致性问题,尤其是在共享页眉、页脚和设计系统等组件时,需要在多个存储库中维护。
继续使用 monorepo 并将代码集中到 packages 中,使得共享组件能够保持一致,同时可以灵活划分关键区域。我们采用了 Turborepo 和 Dependency Cruiser 等工具,以便简化分区和依赖管理过程。
图片
Vercel 的 monorepo 采用“apps”文件夹中的独立微前端结构,同时提升共享包以实现所有应用程序的无缝访问。
通过功能标记,我们逐步将流量从单体前端应用转移至新的微前端应用,从而在删除旧代码前验证性能改进并将风险降至最低。一旦新页面稳定运行一周且无错误,我们便从现有应用中移除旧代码,从而逐步减少依赖并缩短构建时间。
图片
在增量迁移期间,页面同时存在于原始前端整体和新的微前端中。功能标志控制路由,直到微前端版本完全上线。
借助 monorepo 设置和垂直分区方法,我们得以快速行动,保持一致性并缩短构建时间,同时让整个开发过程始终清晰、简单。
吸取的教训和管理权衡
在成功实现 Vercel.com 的微前端架构后,我们将同样的方法扩展到其他项目,例如 2024 年 Next.js Conf 页面。此页面作为独立于 nextjs.org 的应用运行,得益于新架构,不同的区域可以独立提取为单独的应用程序,从而加快开发周期。Next.js Conf 团队和 Next.js 开发团队可以快速、独立地迭代更新。
然而,迁移过程中仍然面临挑战。为确保性能不受影响,我们采用了 Speed Insights 等工具来实时监控用户体验,并使用 Vercel Toolbar 跟踪布局转换和交互时间警报,确保页面响应性达标。
我们也意识到在本地和预览版环境中测试微前端相当困难。例如,草稿模式等功能不稳定,而性能瓶颈(如硬导航)更是常见问题。为了解决这些问题,我们应用了预取和预渲染策略,借助 Chromium 的推测规则优化用户体验。
平衡性能与资源使用的策略
为降低硬导航的延迟,我们首先加载初始页面资源(JavaScript 和 CSS),在链接可见时提前填充浏览器缓存。这样用户导航时,资源可以立即从缓存中加载,减少等待时间。但页面仍需渲染并获取其他资源(如 HTML)来完成加载。
我们更进一步,在用户交互(例如点击链接)时预渲染页面,使页面在后台完成渲染和网络请求处理。这样当用户到达页面时,体验更接近即时加载。通过在适当时机执行预取和预渲染,我们在性能与资源使用之间取得了平衡,避免设备过载,同时提供了流畅的用户体验。
图片
页面在用户交互时预渲染或预取,提供流畅的导航,同时优化性能和资源使用
展望
随着迭代速度的加快,我们正在全力推动整个平台的微前端发展,重点优化路由、简化预览工作流程,并提升硬导航性能。同时,我们正致力于增强仪表板体验并解决工作流程中的挑战,以全面提升微前端开发的效率。
向垂直微前端架构的转变显著提升了开发速度和构建效率。团队现在能够更加独立地工作,同时通过共享软件包保持一致性,形成了一个在自主性和统一性之间取得平衡的系统。
随着我们不断优化这一架构,团队对其潜力充满期待。无论您是在探索微前端,还是偏好单一应用模式,Vercel 致力于提供最佳的开发者体验。