Skip to content

腾讯云国际站前端困境分析

困境分析

前端组项目管理维度分析

  1. 代码管理比较杂乱,甚至不在一个仓库组;
  2. 同类型项目技术栈不统一;
  3. 没有统一的代码检查脚手架等配套设施的支持;
  4. 没有较好的复用库、组件、工具等;
  5. 项目 owner 较大的管理成本、开发同学不一致的开发体验及较高的上手难度。

项目管理纬度

核心官网架构维度分析

项目管理纬度

多个需求多人开发涉及多个页面,开发和稳定性成本急剧增高。

期望

前端组项目管理期望

统一的"篮子"; 统一的脚手架; 统一的代码检查把控代码质量; 统一的基建; 统一的 CI/CD。

官网架构期望

模块隔离: 不同业务模块之间通过不同工程的方式相互隔离,实现业务模块的解耦剥离。 模块间通信: 制定统一的通讯方式,使不同业务之间可以实现数据的发送、缓存、通知。 部署方式: 不同业务之间可以独立开发、构建、部署,只有特殊情况相互影响需要同步部署例外。 复用性提升。 增量迁移: 遗留系统增量迁移。旧代码通过业务剥离之后,可以针对不同的业务模块进行渐进优化。 渲染优化: 使用成熟的 SSR 服务端渲染方案,优化路由并拓展对 ISR 增量再生支持。

规划: 三个优化方向

前端组项目管理优化: 单一大仓优化代码管理策略。 官网架构设计优化: 微前端对官网模块分解成单个应用,进行独立开发、部署和运行。 官网架构渲染优化: 采用成熟 Next 框架进行 SSR 服务端渲染重构。

大仓和微前端方案调研

大仓方案调研

WHAT

项目管理纬度

  1. 多仓 Multirepo: 最常见的代码管理策略,每个工程一个 repo,自由度高,但仓库比较分散。复用比较麻烦;每个 repo 需要自行搭建构建系统、依赖管理、单测等配套设施,可能出现重复造轮子;分支管理、changelog 管理、发布可能相对混乱,不一致。
  2. 单仓 Monorepo: 多个工程放在一个 repo,方便管理。统一的配套设施,更加便捷的复用,但对相关建设有更高要求。体积也更大。
  3. 大仓: 大型规模的单仓。单仓有不同规模,比如小组级、部门级、中心级、BG 级、公司级,比较典型的公司级大仓 Google3 和 BG 级大仓 我司 PCG 大仓。大型规模并没有严格定义,除却规模并且对应规模需要的基础建设支持。

WHY: 研效提升,一致性和复用性的提升

项目管理纬度

除了固有的挑战,它可以实现工业化,放大其它的流程/工具的收益;但是如果没有足够有效的工具和严格的流程及实践控制,大仓几乎就是灾难的代名词。

  1. 单仓想要达成预期效果需要工具、流程和文化三方面的准备,以及长期大量持续维护。
  2. 大量的工具支持以及工程实践成本: 包括不限于代码检查、自动化测试、持续集成、开发流程标准化、工具统一化工作。
  3. 单仓挑战: 由于多个项目在同个仓库中所带来的治理挑战。
  4. 大仓挑战: 由于仓库的体量导致的可扩容性挑战。

HOW: 构建系统/依赖管理

  1. Bazel: 构建系统,有一定的学习成本,需要对构建系统有较深的理解。调研反馈用户体验不好、生态差,最主要是太重了。实际场景是我们目前只有前端大仓单语言的规划。
  2. Yarn workspace+Lerna: 前端 Monorepo 使用最多的方案,但存在命令不统一、发布速度慢、Phantom dependencies、NPM doppelgnger 等问题。
  3. PNPM workspace(推荐): 快速的,节省磁盘空间的包管理工具,由 npm/yarn 衍生而来,解决了 npm/yarn 内部目前潜在的 bug,且极大了地优化了性能,扩展了使用场景。不提供内置发布工作流解决方案,官方有 2 个比较好的建议 Rush 和 changesets。

项目管理纬度

PNPM 的优势

项目管理纬度

  1. 快速;
  2. 高效: 节约磁盘空间并提升安装速度。使用 npm 或 yarn,假如 100 个项目使用了某个依赖,就会有 100 个副本。而使用 pnpm,只会有 1 个内容可寻址的仓库,所有文件都是通过硬链接的方式。而当你需要用到某个依赖的不同版本,它也只会将差异文件添加到仓库;
  3. 严格: 创建非扁平化的 node_modules。之前在使用 npm/yarn 的时候,由于 node_module 的扁平结构,如果 A 依赖 B, B 依赖 C,那么 A 当中是可以直接使用 C 的,但问题是 A 当中并没有声明 C 这个依赖。因此会出现这种非法访问的情况。pnpm 很好地解决了这个问题,保证了安全性,规避非法访问依赖的风险;
  4. 非常适合 monorepo: 内置支持单仓多包。

项目管理纬度

微前端方案调研

WHAT

项目管理纬度

WHY

  1. 各个子应用能够单独开发、维护、部署。它们可以由多个团队开发,每个应用都是单一职责,相互间不存在明确的依赖关系。
  2. 聚合前端应用。微服务架构,可以解耦后端服务间依赖。而微前端,则关注于聚合前端应用。
  3. 应用自治。只需要遵循统一的接口规范或者框架,以便于系统集成到一起,相互之间是不存在依赖关系的。
  4. 单一职责。每个前端应用可以只关注于自己所需要完成的功能。
  5. 应用的拆分基础依赖于基础设施的构建,一旦大量应用依赖于同一基础设施,那么维护变成了一个挑战。
  6. 拆分的粒度越小,便意味着架构变得复杂、维护成本变高。

HOW

项目管理纬度

选型确定 项目管理纬度

服务端渲染方案调研

项目管理纬度

前端“大仓”建设

项目管理纬度

结构管理

结构目录设计

项目管理纬度

脚手架

项目管理纬度

qcintl-tool 目录搭建了一个基于 commander+inquirer+chalk 的脚手架工程, 相关命令已写入大仓自定义命令集,执行 pnpm create:xxx,即可初始化对应工程 (WIP)

项目管理纬度

代码复用

  1. 仓内: PNPM Workspace 通过 pnpm workspace 我们可以方便的链接工作区工程。
  2. 仓外: NPM Package 发包管理较为繁琐,一次更改,需要提供方发包流程,调用方走上线流程,同时注意版本的管理。仅适合对外

项目管理纬度

仓内复用

项目管理纬度

在大仓下,我们对公共代码的调用可以变得更简单: 直接从代码层面依赖,而非必须使用包管理/制品/跨仓库的依赖。 One Version 单一版本,无需进行版本管理。 PNPM workspace 让我们可以方便的链接工作区工程。

项目管理纬度

项目管理纬度

仓外发包管理

项目管理纬度

changesets 流程

项目管理纬度

changeset 组成 项目管理纬度 具体步骤

项目管理纬度

开放协作

大仓模式下, 我们可以更方便地主动去为其他组的项目提交代码,例如修复缺陷或实现我们所需的新功能。

项目管理纬度

代码治理

  1. 代码检查流: husky+lint-stage+eslint+prettier 搭建代码检查工作流,每次提交增量美化代码,同时进行 eslint 检查修复。
  2. commitlint 规范提交: 前端大仓配置了 commitlint,commit message 不规范会阻塞提交。
  3. commizen 提交支持: commit 规范不熟的话前端大仓也提供了 commitizen 可以提供自动选择,已添加到自定义命令集中运行 pnpm commit 即可。

项目管理纬度

版本控制

压缩合并

  1. Merge: Merge Request 使用默认合并策略,会将特性分支上的所有内容都带到主干上来,我们可以看到看到极端复杂的网络图,在大仓中这个问题更是被放大。
  2. Squash: 相当于做了一次隔离,让复杂留在特性分支上,留给分支负责人去关注,而团队只关注主干即可,可以直接由评审人把控主干提交质量。
  3. Rebase: 直接 rebase 到主干并不能解决主干提交信息庞杂的问题,而本地 rebase 比较考验开发人员的素养和 MR/CR 质量,需要时间成本和各分支开发同学的学习和维护成本,后期可逐步规范。

项目管理纬度

  1. 所有变更会被打包成一个提交。这也给了我们机会去认真编写一个完整优质的提交信息,来描述我们一次修改的意图。
  2. 减少了我们代码库中的孤立变更集,极大的提高了我们主干分支上的提交质量,确保只存在独立且自包含的变更集。
  3. 分支历史记录变的非常简单,极大的简化了我们仓库分支网络图,不会看到不必要的无关分支网络图。
  4. 让开发人员可以自由地在特性分支做实验,提交不完整的变更集。一旦合并,只会显示最终结果。
  5. 不必担心新人、临时成员或外部成员做出的不规范提交,我们甚至可以用 Web 界面来完成代码更改,随意做出任何提交注释。
  6. 最终的 MR 仍然会经过检查和 Code review,评审人有义务对变更集和提交注释做最终的决策和适当的修改。
  7. Merge Master 在工蜂 MR 时选择 Squash Merge 并选择删除源分支,同时本地也要注意,这里我们不能直接复用源分支,需要自行删除,保证 MR/CR 不会有重复。
  8. 因为如果继续复用分支做提交,最后在工蜂发起新的 MR 时,由于 commit 历史记录的区别,会导致显示出额外的 diff 信息,增加 review 的成本。

分支模型

项目管理纬度

权限控制

提交权限

  1. 提交权限在 CR 层面解决,引入类似于 Chromium 的 OWNERS 机制。机制的关键在于:OWNERS,而非 commit 的作者,为代码质量负责。 项目管理纬度

  2. 在大仓下手动寻找正确的 reviewer 会相对更困难,因此我们通过工蜂提供的 API 自动为 commit 自动分配 reviewer,同时通过企微机器人拉群通知。 项目管理纬度

可见权限

  1. 一个不太常见的、与大仓的设计目的相反的需求是隐藏代码,但是有一些敏感代码是必须需要维持私密性的。
  2. 我们可以私密代码放入小仓中,以小仓的权限控制来保证保密性。大仓保持所有代码的可见性。
  3. 如图类似场景,coding 配置中心单独的配置小仓。 项目管理纬度

代码评审

  1. 基于 MR 的 CR: 通过工蜂和流水线配置,MR 的时候会主动发起对应目录责任人的 CR。
  2. 培养代码评审文化: 定期举行 CR 评审会,对当前周期即将上线的模块开展 CR 评审会,同时对当前周期“基于 MR 的 CR”进行一次复盘。 项目管理纬度

持续交付/部署

大仓模式下, 如果每个项目都有独立的几条流水线,整体的流水线也会非常大。存在巨大的管理和维护成本,也不利于后续扩展。所以我们要对流水线进行集中治理和标准化。 项目管理纬度项目管理纬度

微前端实施拓展

项目管理纬度

MultiZones 实施

将官网转变为多个小型化的多个 Next 应用,完全独立,然后通过 MultiZones 方案在表现形式上聚合为一个统一的应用。各个子应用能够单独开发、维护、部署。 项目管理纬度

应用间通信

项目管理纬度项目管理纬度项目管理纬度

跨应用预加载

Next 提供了预加载的能力,但是跨应用无法预加载。我们自研了一个组件,在可视区展示或者鼠标移入时,拿到跨应用资源列表,进行跨应用的预加载。 项目管理纬度

增量迁移

项目管理纬度

  1. 第一个策略是配置代理,使特定子路径下的所有内容都指向新的 Next 服务,其他内容还是指向之前的服务,从而实现增量迁移。
  2. 第二个策略是项目根域直接指向 Next 主应用,主应用将一些子路径代理到之前的服务,从另一个角度实现增量迁移。

项目管理纬度

代码复用升级

模块联邦实现远程共享,更加优雅的实现跨应用代码共享。异步方式提供和使用共享模块,相对节约资源。共享的模块发生修改之后,使用方无须重新发布,但也不被缓存。 项目管理纬度

不足与展望

缺陷与不足

ModuleFederation 的使用,以及对 Next 的支持: 代码复用在 next 应用中无法比较好的使用 MF,而是使用的 pnpm workspace,无法做到复用场景在非 SSG/ISR 动态更新, 是否需要 MF 值得再次讨论。 基建不够: 工程初始化、部分基建及管理成本得到了降低,但是脚手架支持不完全,持续部署交付标准化还不够,持续集成单测能力还缺失。 主干开发未启用: 基建的不完全,较大的学习成本,使我们暂时没能启用主干开发。 文档不够完整: 文档不全,新上手的同学无法全面快速接手,进行迁移开发。

未来展望

文档补全,前端组项目大体全部迁入; 基建补全: 自动化测试、更多大仓相关工具支持; 模块联邦; 标准主干开发; Bazel 化。