| 导语 TDesign 是腾讯各业务团队在服务业务过程中沉淀的一套企业级设计体系,于2021年12月底正式对外开源,官方支持了众多业界流行的开发技术栈,多个仓库同步迭代推进。目前来自公司内外,包括设计师、开发者在内的很多同学都大规模参与到了 TDesign 的开源共建活动中。怎样协调大家一起工作,如何保障组件库各个技术栈产物实现的一致,本文主要讲讲从工具方面的思考。
腾讯公司内的开源协同活动这两年进行的如火如荼,各个领域内开源项目也逐步孵化出来,我在找资料的时候偶然找到 19 年的一篇对腾讯开源相关负责同学的采访稿,不太了解腾讯为什么推行内部开源协同活动的小伙伴可以先看看了解下背景:超两万技术人员如何减少重复造轮子?腾讯推进内部开源协同。
TDesign 前端通用 UI 组件库开源项目 从 2020 年创立至今已经走到了它的第三个年头,与公司其他众多开源项目相比,我感觉同时存在以下特点:
1、参与人数众多;
2、多技术栈同步迭代;
3、设计师角色参与度相对较高。
我会针对这三点,浅谈下怎样用工具和流程来保障大家可以在开源项目这样的组织形式下,相对顺畅的一起协作。开源协作里的“人月神话”
熟悉软件工程的小伙伴们肯定都熟悉这本书:《人月神话》,大部分时候人力和时间都不是线性相关的,越多的人未必意味着可以越快的完成某项任务,举个创业的小例子:很多公司最初可能是从最简单夫妻档开始的,两个人共担风雨,这时候沟通的成本是最小的,没有上下班的限制,有什么想法都可以随时沟通。当我们找到了一群志同道合的朋友,决定一起创业,没有工位,大家都在一张桌子上办公,可以在一张桌子上解决日常所有沟通问题,很多人心目中理想的敏捷团队的标准,就是“一张桌子可以放的下所有人”。随着想做的事情越来越大,人也越招越多,我们甚至没办法拉所有人一起开会了,那么就需要一种架构和形式把这么多人组织起来,最终的形式就是“开公司”。随着人员数量的增长,沟通的成本会不断上升,更充足的人力带来的价值,迅速的被的复杂组织结构所消耗。开源协同的提供给了我们一种新的,不同于公司组织架构的形式,以开源项目这种虚拟组织的形式可以让大家脱离原有组织架构的限制,不受职级高低、团队 OKR 考核的影响,能够跨团队、跨 BG 的进行协作,任何人都可以为开源项目做贡献,以 tdesign-vue-next 仓库为例:参与贡献的同学很多,这是 TDesign 项目“甜蜜的痛苦”,组织大家一起参与共建,保障项目流畅的运行,其实也是件很有挑战的事情。线下同步 vs 线上异步
开源协作模式下大家的沟通方式会有比较大的差别,当大家都在同一个实体团队时,更多是在会议室里,面对面的直接讨论。在开源协同下,大家都变成了网友,进行的更多的是线上,基于文档或提案的异步交流,可能会更慢。但好处是,“异步”,而非面对面或者即时通讯工具上的交流,给大家留出了更多思考时间,说出口的话,和落在文档中的文字是不一样的。GitHub Discussions
开源社区中更多的是使用提案等方式进行讨论,提案使得大家的讨论过程能够留存下来,我们的每一个最终方案,都可以追根溯源。目前 TDesign 的开源协作也在努力从群聊沟通为主,逐渐增加 GitHub Discussion 的比例,TDesign 近期的一些重要讨论,如 # 发布正式版本需要达到什么标准、# 如何适配 Vue 2.7,或者一些组件 API 的讨论 # Calendar 组件 API 讨论 等除了线下群里的讨论等也在 Discussion 中记录以及和外部社区的小伙伴们交流。GitHub Issues
GitHub issue 大家应该更熟悉一些,最常用的能力是用户反馈 Bug,除此之外之外我们也应该把它看作开源项目主动对用户和贡献者主动推送信息的重要渠道:让大家知道开源项目最近在做些什么。相关在做的一些事情可以在汇总在一个 issue 中,方便大家查看进展:桌面端新组件招募 。开源项目的一些运营活动,除了通过内外网的公众号、KM 等渠道,GitHub Issues 也是很好展示地方,贡献者和使用者都很习惯于经常查看仓库的 issue 列表:# 「技术向善,助力 TDesign 无障碍改造」主题活动开始啦Issue 流转
即使我们仅仅把 GitHub Issues 用作反馈收集,也很容易有漏处理或者需要自己当人肉转发器找具体同学修复的情况,TDesign 的各个仓库中设置了一系列的 Github Action 流程,来实现 issue 的自动 assign 给对应的同学,通知、截图,把大量需要人工完成的事情,改为自动的,提升效率。并让贡献者可以在第一时间收到仓库的反馈,明确具体的处理者,获得更好的贡献体验。通过这套机制可以保障 issue 顺畅地流转,防止漏掉用户的反馈信息。对应的各个仓库企业微信群里,也配置了相关的机器人帮助即时同步,定期汇总 Issue 和 PR 情况 。PR 自动化
TDesign 都给 Issue 和 PR 提供了 template,template 在一定程度上提高了用户的门槛。需要用户按照一定的格式复现出 Bug 的场景,这算是种取舍:1、增加了用户反馈的时间成本,也是在引导用户先行思考问题原因,屏蔽自己项目中其他因素的干扰;
2、减少贡献者复现和排查的时间,更方便问题快速解决。
PR 中也提供了 template,让贡献者提供本次 PR 相关信息,便于 PMC 同学 review 实现,同时也便于每次发布版本时,根据这些结构化的 PR 基本信息自动生成 changelog,以 tdesign-vue 0.50.1 版本发布为例,提交 release/0.50.1
分支的 PR 后可以自动生成本次发布的日志初稿:除了提 PR 时的 template,更重要的是通过 CI 自动检测本次改动的测试用例、风格检测以及部署本次修改的预览地址等,降低 PMC 同学 review PR 的难度,加快 PR 合入的速度:想要了解每次 PR 跑了哪些 CI 环节,可以参考 test-build.yml 。Wiki 和 Projects
GitHub 仓库除了呈现代码外,还需要承载文档的沉淀,TDesign 将所有之前在公司内维护过的文档,及内网仓库中的一些重要讨论 issue 全部迁移到了 GitHub wiki:https://github.com/Tencent/tdesign/wiki 及对应技术栈仓库中另一个大家可能比较少用的功能是 GitHub Projects (beta),在尝试过公司 TAPD 外部版本、腾讯文档、Notion 等文档协作工具后,我们最终还是决定回归 GitHub,跟代码及 issue 社区保持最近的距离,把它作为开源项目的看板工具管理项目的整体运作,当某项任务关联 PR、Issue 等状态发生改变时,可以自动在看板中更新任务状态,展示进展百分比等。
多技术栈:是优势也是负担
以上分享了基于 GitHub 等社区和一些 Actions 基础设施,我们可以把公司内外的很多贡献者组织起来一起贡献,还有个问题是怎样同时维护 Vue/React/微信小程序等不同技术栈产品。跟业界其他同类组件库产品相比,TDesign 的一大特点是官方提供了很多业界主流技术栈的支持,这在落地推广时回有很大优势:业界目前还没有统一的前端技术栈,腾讯公司内各前端团队也都在根据自身实际需求,选择适合自己的开发技术栈,使用 TDesign 可以让团队的技术选型不受组件库选型影响。但同时维护这么多仓库,压力也很大,而且很难保证各个仓库实现的组件 UI 和 API 完全一致,TDesign 项目中通过长期实践总结了一套通过流程和工具来保障的手段。样式复用
TDesign 的 UI 实现(Less/css)等统一在 tdesign-common 实现,各个技术栈仓库,都以 git submodule 的方各自引入自己的仓库中,直接复用已开发的 Less 产物,当 UI 需要调整时,统一在 common 仓库修改,再同步各仓库,在各仓库实现的组件 DOM 层级结构一致的前提下,可以保证各个技术栈的同个组件 UI 也一致。API 维护平台
TDesign 的通用组件,从需求讨论到上线会经历以上各个流程,除了最后的上线前 code review 和设计师走查环节保障实现效果外,最重要的一个环节在进入开发前的 API/交互稿评审环节:我们会邀请技术栈 PMC 负责同学、交互设计师、视觉设计师、UI 开发同学、API 制定者、各技术栈开发同学在内的各个角色一起参与评审,讨论的内容主要是:1、API 设置是否满足业务场景需求,是否留有扩展空间(组件易用性与灵活性 trade-off);
2、API 描述等是否框架无关,能够在多个技术栈中实现;
3、交互稿是否满足需求,是否提供了所有场景的 demo。
会议结束后 PMC 同学会讲讨论定稿的 API 提交到 tdesign-api 项目的 API 管理平台上,作为各个技术栈的组件实现标准。tdesign-api 中实现了一套基于 GitHub Actions 开发的自动同步机制,可以把 API 自动提交到对应的仓库中:对于具体组件的开发者来说,开发过程中所需要的 API 定义、文档描述、需要展示的 demo 场景等都已经通过平台直接生成,没有二次理解的成本(或者发挥的空间),直接依照这些产物进行代码编写即可。技术栈共建
虽然我强调了“官方”支持众多技术栈,但其实大多数时候也都很难仅仅依靠现有 PMC 组织规模,就能覆盖所有技术栈产品,尤其是在大前端领域内,各类技术栈差别很大,除了 TDesign 自身的开源项目成员我们也在跟公司内外的很多团队合作共建。公司内 Flutter 开源项目 的同学除了在做自己领域内的相关工具和生态建设,也牵头在做 TDesign 移动端组件库的 Flutter 实现版本,目前已经有很多组件完成了开发并部署了体验官网,欢迎去 GitHub 关注仓库 tdesign-flutter 。公司外部也有类似的团队和个人在为 TDesign 贡献不同的技术栈实现,比如在 .NET 社区比较流行的 Blazor 技术栈,现在也有 .NET 社区的热心同学在参与维护 AchievedOwner/TDesignBlazor。这些新增的技术栈,我们计划也用 tdesign-api 同步管理和生成 API,从源头管控加后面的 review 和验收才能保障最终各个技术栈实现一致。“通用”和“易用”的取舍
TDesign 在做组件的过程中,最常遇到的需求或者咨询问题就是:1、“xx组件可不可加支持这个功能呀?”
2、“可以新增个组件不?我们的业务经常用到”。
TDesign 本身定位是通用 UI 组件库,很难满足所有种类的业务需求,很多时候增加了一个不常用的 API 对大多数用户来说意义不大,额外增加了记忆和查找的心智负担,变得不够“通用”了。但对于很多团队来说这部分功能又是有需求的,缺少后日常业务中又达不到开箱即用的“易用性”要求。经过长期实践,我们在产品生态上对通用组件库和业务组件库做了概念和定位上的区分:PMC 团队依然对 TDesign 的通用组件库部分保持了克制的态度,新增功能或新增组件类型都需要经过 PMC 例会讨论通过。各类不那么通用的需求,则由开源项目与公司各个业务团队合作的方式,由一线使用的同学基于 TDesign 做二次封装,形成适合特定行业领域的业务组件库,目前已经有政务、智慧零售等领域的业务组件库产品。同时各业务组件库中符合通用要求,PMC 团队通过的组件,也会反哺进入到通用组件库中,比如内容平台团队沉淀出来的的 Watermark 水印组件最近就纳入到了通用组件库。让设计师们“发声”
公司在 21 年成立了设计领域委员会,来指导包括 TDesign 在内的设计相关开源项目的运作,打破了以往公司内技术委员会没有设计师群体的情况。TDesign 作为公司统一设计体系建设的承载项目,有大量设计师同学参与其中,但在一开始设计师们参与开源共建却并不顺利。问题主要集中在设计师开展做稿子的工具,和开源协同文化的传播上。“硬件” - 设计协同工具
TDesign 项目刚启动时,设计师们的稿子还都是用 Sketch 来做,产出的设计稿文件好一点的会通过 Codesign 分享给其他设计师和开发同学,不传 Codesign 的就只能企微直传文件了,缺点显而易见,一方面基于本地文件的设计资源,很难进行版本管理,硬盘被逐渐填满:这种基于文件的协作,只能人工处理每一次修改后导致的细微冲突,无法满足设计师之间协作的需求。好在目前业界比较流行的 Figma、Codesign、即时设计等产品都支持了线上协作能力。大概 21 年开始, TDesign 组件库的设计资源都会优先维护 figma 版本,它提供了与开发者习惯的代码管理工具相似的 fork 能力:Figma tutorial: Branching & merging可以看出 Figma 在使用开发领域已经非常常见的代码管理和分享方式来管理设计资产,提供了类似 Git 的切分支,merge 修改等体验。设计师在获取设计资源并做修改后,依然保留了与原始文稿的关联关系,当有更新时会收到消息。TDesign 的设计师会在每次资源更新时,给出本次修改的详细更新日志,帮助其他设计师同步更改内容。通过 Sketch 到 Figma 的设计工具的转变,我们解决了设计师之间设计资产难共享、难协作的问题。更进一步,我们尝试了通过 Codesign 的能力来解决设计师与开发者之间协作沟通的问题。以一个样式中阴影的实现为例:可以看到设计工具和对应的代码实现之间存在很明确的对应关系,在设计交付环节貌似不存在双方理解偏差导致的实现不一致的问题,但事实却是我们可能会在某组件开发群里看到这种对话。即设计师与招募来的开发者反复沟通到底要调整阴影哪里的设置,大部分开发者可能完全不了解“出血位”等属于设计师的专属“黑话”。实际上不单组件库的场景,普通业务前端开发中也经常遇到这种设计师与开发者理解不一致,在设计验收环节返工的情况。解决办法一种是不做这种跨角色沟通,我一人全包干!比如我们这位设计老哥,他最近真的的学习写代码,并且在上周刚刚在 GitHub 上提交了第一次 PR:当然这很难,实际上不太可能一个人完成所有工作,各专业角色间一定存在门槛,从效率方面看也需要专业的人做专业的事。好在已经有很多工具可以帮我们去做这些中间概念的转换,比如 Codesign 中可以直接生成设计稿对应的代码产物,开发者可以一键复制代码实现,也不需要反复沟通怎样修改才能达到自己的诉求。这是“硬件”上或者说工具的解决方案,在实践中我们还会发现想要设计参与开源,存在一些“软性”的问题。“软件” - 设计师的开源文化
我们很多时候要尽量少给别人贴标签,但客观来看设计师和工程师确实存在不同的群体风格:一边是更注重个人创意和灵感的设计师们,另一边是推崇代码共享的工程师们。很多优秀的设计师朋友可能不习惯于在 GitHub 上交流,也不太熟悉怎样通过开源社区,参与开源项目。今年以来我们也在尝试,在设计师群体内可以推广开源文化,比如在 GitHub 的 issue 中,除了以往大家比较常见的 Bug 修复或者新特性的 help wanted,我们也增加了很多设计资源共建的任务,通过跟运管的公司内部 issue shoot 活动,以及我们在设计相关公众号等渠道做的设计共建运营活动等,成功招募到了很多优秀、热情的设计师同学:目前包括 Axture、Sketch、Figma 在内的主要设计资源,都有外部设计师参与维护。就像一家公司中不可能只有一种岗位一样,现实中的开源协作也不应该只有工程师参与,多种角色沟通、碰撞,更容易激发灵感,越多的人参与,也更能让开源这件事可以持之以恒。目前 TDesing 中除了开发、设计师角色,也有公司内专职运营的同学在通过开源的方式在参与共建,帮助我们从专业运营的视角来规划、复盘很多运营活动。来点儿不那么“工具”的
开源应该是一件人人受益的事情,开源社区是否活跃很大程度上决定了这个项目能否长久的运营下去。所以我们最后聊点儿不那么工具的:除了给使用组件库的用户带来价值,每一位参与到开源共建活动中的小伙伴都应该能从中得到荣誉、纪念品或者其他激励。从我接触到的大部分参与贡献的小伙伴来看,相较于金钱的激励,大家更看重的是来自社区的认可和那些精心准备的有代表性的文创周边,比如可以穿在身上的定制文化衫:如果你的项目刚刚起步,这些都给不了其实也没关系,从每一次及时回复别人的 PR 开始。从 GitHub 仓库 Readme 里的致谢开始,或者只是在每一次发版时自动生成的 New Contributors 提示:让贡献者感受到被重视,倾听大家的意见,不仅仅对外开放代码,也开放讨论和决策过程,维护好整个社区的讨论氛围,这些可能比很多刻意的推广宣发都更有意义。TDesign 已经走到它的第三年,比很多公司内的刚刚孵化出来的新开源项目走的远了一些,在磕磕绊绊中积累了一些经验,同时也比很多业界同类的前辈们要显得年轻、稚嫩,很多时候还不知道怎么应对来自业界审视、探讨的目光。在三年的这个时间点回头看看,发现做开源最重要的不是代码,而是通过开源社区认识到的这些有心、有爱、有趣的伙伴们。