羚珑项目架构演进:从 V3 到 V4 的优化之路

430 阅读10分钟

背景

羚珑是一个内容生产与管理一站式服务平台,提供海量京东版权素材和强大便捷的图片编辑功能。在前端架构上,羚珑主要由羚珑平台、编辑器和小工具集三大模块组成。

•羚珑平台:提供用户的前台操作,包括空间管理、模板推荐、模板管理和素材管理等页面

•编辑器:羚珑项目的核心模块,用于图片编辑和视频编辑

•小工具集:羚珑AI智能工具的集合,包括图片处理、一键生成和效果提升等三大类型的工具

本文将介绍羚珑项目从羚珑 V3 架构到 V4 架构的架构演进过程,探讨其中遇到的挑战和和优化体现,以及它们对项目的影响和效果。

羚珑 V3 架构

在羚珑 V3 架构中,采用了 Monorepo 的方式将所有相关的项目代码存储在同一个版本库中。这意味着羚珑平台、编辑器和小工具集三大模块的代码都被统一存储在一个版本库中。

为了有效地管理这样的大型代码库,采用了 Yarn 和 lerna 工具来进行管理。

Yarn 是一个流行的 JavaScript 包管理工具,而 lerna 则是用于管理具有多个软件包的 JavaScript 项目的工具。通过这种组合,可以更好地管理代码依赖关系、版本控制以及项目之间的交互,并且能够更方便地进行开发、测试和部署。

Monorepo 的项目管理方式很适用于项目前期由一个前端团队负责羚珑下所有模块的组织架构,可以很方便的复用代码。

但是随着项目规模的增长,为了提高开发效率,羚珑项目改成由不同的小团队负责不同的模块,高效开发,快速迭代,而原来的 V3 架构也不再满足羚珑项目的需求,有以下问题需要解决:

1.项目庞大,历史包袱重,在 Monorepo 内部代码耦合严重,开发人员的心智负担很高

2.公共组件难以复用,体验不一致

3.依赖众多,安装依赖速度慢,编译速度慢,严重影响开发效率

羚珑 V4 架构优化

为了解决上面的问题,在 V4 架构中,从 Monorepo 切换到了 PolyRepo + Monorepo,同时我们还做了以下优化工作:

1.解耦项目: 将羚珑平台、编辑器、小工具集、公共库进行解耦,分成 4 个独立的前端项目,独立开发和部署,采用松耦合设计可以让每个项目单独更改和维护,降低开发人员的心智负担,同时也减少问题的潜在风险

2.公共库拆分: 新增 ling-service、ling-style、ling-store 等子包在公共库中,用于管理公共逻辑和样式。通过公共库的管理,可以让其他项目方便地复用羚珑项目提供的组件和函数,公共库包含以下子包:

◦ling-core:存放羚珑原子组件库,是基于 ant-design 进行过主题定制,符合羚珑视觉规范

◦ling-biz:存放可复用的业务组件,消费 ling-core 原子组件,不可直接引用 antd 组件,便于统一管控

◦ling-helper:存放可复用的公共类库,需脱离具体开发框架的依赖

◦ling-service:对服务端接口的直接封装,可提供接口响应数据格式化方法

◦ling-icon:存放 ant-design/icons 满足不了的图标 svg 文件

◦ling-style:提供统一的样式变量以及 mixins,所有样式文件均需基于此仓库定义的变量,其他应用引用时,不可写死值

3.公共库支持 npm、mf 两种方式对外发布: 使其更好地对外提供使用,实现跨项目复用

◦npm 组件共享:稳定性高但发布流程长,适合稳定性要求高的项目

◦mf 组件共享:发布更新快但稳定性相对较差,适用于刚启动迭代速度非常快的项目

▪注:mf 组件共享是使用 webpack 5 的新特性 Webpack Module Federation 打造的一套羚珑 mf 组件共享体系,mf 原理及用法详见:《京东零售平台:前端组件资源共享与中心化管理实践

4.采用 pnpm workspace: 使用 pnpm 工具代替 yarn lerna 来管理 monorepo,pnpm 可以更快地安装依赖项,提高开发效率,结合 Turbo 构建工具能够进一步提升构建速度

5.自动化工作流: 通过 Changesets 来打造自动化工作流。Changesets 可以自动化版本管理和自动生成 changelog,减少手动操作的工作量。这样可以减少本地工作流的时间,提高开发效率。

Turpo 构建提速

在 V4 架构中,小工具集、公共库保留了 Monorepo 的项目管理方式,Monorepo 中每个 workspace 可能包含各种任务,如测试、代码风格检查、构建等。随着软件项目的增长,这些任务可能会增加,并且在 CI 流程中可能存在执行顺序和依赖关系。

在 V4 架构中,引入 Turbo 构建工具来优化 Monorepo 的构建流程,Turborepo 可以通过读取项目中的 package.json 和 turbo.json 等配置文件,并利用其中定义的脚本和任务依赖关系来管理这些任务。通过合理配置,Turborepo 可以使任务的执行速度最大化,同时处理好不同 package 之间的依赖关系,以提高构建效率和整体开发体验。

Turborepo 主要有以下优点:

•增量构建: Turborepo 会记住你之前构建的结果并跳过已经计算过的内容

•感知内容 hash:Turborepo 通过文件的内容,而不是时间戳来确定需要构建的内容

•并行处理:不浪费任何闲置 cpu 性能,以每个核心最大的并行度来执行构建

•远程缓存:与团队成员、CI/CD 共享远程构建缓存,以实现更快的构建

•零运行时开销:Turborepo 不会影响您的运行时代码或 sourcemap

•任务管道:将每个项目里的任务进行拓扑排序再执行,然后让 Turborepo 优化构建内容和时间

•渐进式设计:可以在几分钟内快速集成到项目中

优化前:

优化后:

有缓存的情况下,构建时长从 1 分 40 秒减少到 2 s,做到了实际意义上的秒开了。

Changesets CI 自动化工作流

在 V4 架构中,从 Monorepo 切换到了 PolyRepo + Monorepo,包含了以下 4 个独立的前端应用:

1.ling-editor-workbench:编辑器

2.ling-web-platform:羚珑平台

3.ling-appstore:小工具集

4.ling-design:公共方法

独立应用之间通过 npm 包的方式来进行共享,这就导致当公共库有更新时,整个部署流程变得很长很耗时,影响开发效率。

如果我们发现 ling-design 中的一个方法有 Bug,我们进行修复的时候大致步骤如下:

1.在 ling-design 代码仓库中进行修复以及提交

2.更新 ling-design 的包版本,发布到 npm 上

3.在 ling-appstore 中更新 ling-design 包版本,并进行构建发布

4.更新 ling-appstore 的包版本,发布到 npm 上

5.在 ling-web-platform 中更新 ling-design 包版本,并进行构建发布

6.在 ling-editor-workbench 中更新 ling-design、ling-appstore 包版本,并进行构建发布

通过 Changesets CI 打造自动化工作流来解决这个问题,具体分为以下几步:

1.版本管理: 对于每个前端应用的 npm 包,确保版本号的管理是清晰的。可以采用语义化版本规范(Semantic Versioning)来管理版本号,遵循 MAJOR.MINOR.PATCH 的格式。

2.批量发包: 使用工具来批量发包,遍历每个前端应用的目录,执行 npm publish 命令来发布 npm 包。

3.CI 集成: 在 CI 流水线中集成包发布的步骤。当代码提交或者合并到主分支时,自动触发 CI 流水线进行构建、测试和包发布操作。在 CI 配置中使用适当的 npm 命令来执行包发布操作。

版本管理

ling-design 子包之间存在互相依赖的关系,为了方便管理版本,每个子包都一起发布,统一版本号。

同时 npm 包版本号分为 3 个环境,方便平台引用:

Alpha版本:用于开发人员内部使用或个人隔离的环境,用于自测和初步功能测试。这个阶段的版本可能存在较多的问题和未完成的功能。

Beta版本:功能开发完成后,用于团队共用的测试环境,以便进行更广泛的功能和兼容性测试。在这个阶段,软件可能已经相对成熟,但仍可能存在一些问题需要修复。

Patch版本:是指已经发布的正式版本,在线上使用的版本。

批量发包

Changesets 是 pnpm 官方推荐的一个管理版本以及变更日志的工具,专注于多包管理。

当项目下的某个包有变动时,可以按照以下步骤进行版本变更以及发布,来实现批量发包:

1.运行 pnpm changeset ,将会在命令终端将你当前工作空间所有的包列出来,手动选取需要发布的包,选取版本以及填写变更信息。

2.运行 pnpm changeset version。 这将提高先前使用 pnpm changeset (以及它们的任何依赖项)的版本,并更新变更日志文件。

3.运行 pnpm changeset publish -r。 此命令将发布所有包含被更新版本且尚未出现在包注册源中的包。

CI 集成

将批量发包集成到 CI 流水线中,tag 触发流水线自动发包,开发团队不再需要手动选择包和版本信息,减少了人为错误的可能性。

流水线内置了以下步骤:

1.pnpm publish

1.模拟 pnpm changeset 命令,按照 Changesets 要求的格式,通过脚本创建空白文件,写入需要发布的版本号和变更信息

2.运行 pnpm changeset version,更新变更日志和版本号

3.Git 提交更改并带上 tag

2.tag 变更触发流水线,运行 pnpm release,批量发包

image.png

image.png

小结

在本文中,我们深入讨论了羚珑项目的架构演进过程,从 V3 架构到 V4 架构的优化措施,以及采用 Turpo 构建提速和 Changesets CI 实现自动化工作流的具体做法。

通过这些优化措施,羚珑项目取得了显著的改进,包括更灵活的模块管理、更高效的开发工作流以及更快的构建和部署过程。

这些改进不仅提升了开发团队的生产效率,也增强了项目的可维护性和可扩展性。

参考资料

打造高效Monorepo:Turborepo、pnpm、Changesets实践

【Monorepo实战】pnpm+turbo+vitepress构建公共组件库文档系统

为什么使用 Turborepo 同时需要使用 pnpm workspace?

京东零售平台:前端组件资源共享与中心化管理实践