经过两年多的积累和打磨,OSSA 终于在去年下半年顺利开源。作为Taro生态下的UI组件库,OSSA 一经开源,便获得了Taro官方的推荐。本文将带你了解OSSA的前世今生,并着重介绍OSSA在走向GitHub开源时所遇到的问题和挑战。
经过两年多的积累和打磨,OSSA 终于在去年下半年顺利开源。作为Taro生态下的UI组件库,OSSA 一经开源,便获得了Taro官方的推荐。本文将带你了解OSSA的前世今生,并着重介绍OSSA在走向GitHub开源时所遇到的问题和挑战。
回到2019年的时间节点,微信小程序经过两年的迭代,生态已经日益成熟,行业已经充分认识到小程序的商业价值,各大平台纷纷推出自己的小程序体系。
彼时的严选,业务上想要抓住微信小程序和抖音小程序的流量窗口,进行业务的快速尝试。所以技术上需要同时维护多个不同平台的小程序。技术团队基于研发效能的考虑,在当时确定了多端统一开发的方向。
当时市面上已经有多个多端统一框架可供选择,团队在选择多端框架方面秉承以下两个原则:
- 体验优先:技术的演进是为了更多的承接业务,而体验又是技术赋能业务的基石;
- 技术栈统一:新框架必须与团队原有框架相统一,便于技术演进及后续维护。
在综合考虑体验和技术战之后,我们决定将一部分业务使用多端框架Taro进行开发。选择Taro,一是基于其当时的设计理念,输出的小程序有着媲美原生小程序的性能体验,能够保证业务交付的质量和体验。二是 Taro 基于 React 技术栈,这与严选的技术栈相统一。在选定Taro框架之后,从保证网易严选视觉风格统一以及提升开发体验的角度,我们便开始寻找一款合适的基础组件库。在2019的时间节点,Taro生态下可供选择的组件库还很有限。在调研对比之后,我们发现现有组件库的视觉风格与网易严选现有风格差异较大,而且没有一套称得上企业级的组件库方案。综合考虑之后,我们决定新建一套自己的基础组件库,自建组件库,从长远看,符合业务侧快速迭代、视觉统一以及技术侧效能提升的诉求。
在决定新建组件库之后,我们便联合设计部门成立了 OSSA 评审委员会,负责组件库的视觉把控、评审、规划以及落地工作。经过在严选电商业务中的沉淀和积累,OSSA 初具雏形,整体架构如下图所示。具体的建设过程可以参考《网易严选多端组件库OSSA正式开源》
OSSA 上线之后,一直以来都是在严选内部项目中发光发热。主要是因为想要开源,摆在面前的有以下几点挑战:
- 开源需要面临千差万别使用场景,而OSSA脱胎于严选电商业务,其在多业务通用性存在短板,需要扩充对其他业务场景的适配;
- 企业级组件的可靠性需要让用户信服,正如前面所说,组件开源之后会被应用在各种各样的业务场景中,本着让不同业务的用户用的安心的原则,我们需要提高自身的代码质量和可靠性;
- 严选前端之前并没有对外开源的经验,开始一个开源项目很简单,但是做好一个开源项目需要能够吸引外部贡献者并提供流畅的贡献体验、广泛参与的社区氛围以及省心省力的后期维护。
21年下半年,严选业务侧开始在尝试创新业务,前端团队基于历史多端研发效能和业内竞品的调研,在与各方沟通交流之后,毅然选择了多端统一开发。借助创新项目——猫咖开发的契机,在业务开发中,OSSA 逐渐完善了组件在不同业务场景下的体验,验证了组件库在多场景下的易用性。OSSA在猫咖业务开发中出色的表现,让我们觉得 OSSA 已经具备了推广给更多人、更多业务使用的条件。为了保证代码可靠性和提高可信度,OSSA项目组通过完善的测试用例全方位检验组件,经过多场景多维度的测试,保证了每个组件的功能及后续迭代的稳定性,其可靠性也在猫咖项目中得到进一步验证。
想要在兼顾好日常业务研发,在开发之余维护一个开源项目,就必须想办法吸引更多的外部贡献者。通过参考大量的已有开源项目,并结合我们项目自身特点,逐步完善OSSA社区的能力及体验。当前OSSA已经具有完善的官网及教程文档,并提供了详细的贡献说明,方便其他开发者参与其中。
3. 开源前准备工作
3.1 项目层面
我们主要看下一个开源项目,自身所必须具备的东西。首先看一下GitHub 官方所提供的开源项目应该包含的要素:
3.1.1 开源协议(license)
通过开源协议可以清楚的表明,可以和不可以用你的软件来做什么。目前常用的开源协议有MIT、 Apache 2.0 和 GPLv3 。关于如何选择你的开源协议,你可以通过以下几个问题来确定:
- 你的项目是否依赖其他项目,或者想要被其他项目依赖?
不同的技术社区倾向不同,比如前端的npm项目,基本上都是使用 MIT 协议。而云原生相关的项目基本上都是Apache 2.0 协议。你需要根据项目所处的领域,尽可能的与现有项目保持统一的协议。如果你不希望你的项目在被修改之后闭源,那么你可以选择GPLv3。
OSSA 作为前端 npm 大军的一员,毫无疑问选择的是 MIT 协议。如果上面两个问题不能选择帮你做出选择,那么我建议直接选择MIT协议,既然选择了开源,那么我们就将开源精神贯彻到底,因为MIT协议基本上不对开源项目做任何约束,使用者可以随意使用你的项目。
3.1.2 README
README 文件会被展示在GitHub首页、Npm包首页等很多地方,一般情况下 README 文件会包含以下几个部分:
可以使用简短的语言介绍你的项目是用来干什么的。如果项目有一个炫酷的名字,也可以介绍下名字的来历和含义。如果项目有可以预览的demo,记得贴上链接和二维码。项目介绍中可以使用一些有意思的badge来增加美观度,badge可以从这里获取。这部分需要介绍下如何从0到1使用你的项目,这部分不需要介绍特别详细的项目配置,只需要让其他人根据这部分的介绍,可以跑起来他自己的项目即可。虽然对开源项目来说,最好所有的交流都在可以被所有人看到的地方进行,比如GitHub Discussions 和 issues,但是在些地方交流总归不太及时。所以,可以建一些即时消息的群,用于更便捷的交流,当在群里达成一些共识和协议时,最好也能在GitHub上同步一份。即时消息的平台,国内一般使用微信、钉钉以及飞书等,钉钉和飞书只需要贴上相应的群二维码就可以很方便的进群。需要注意的是,微信群的二维码只有7天的有效期,并不适合直接在介绍中直接放微信群二维码,解决方案有两种:一是放个人微信号和二维码、先加个人好友然后再通过发送特定关键字自动发送加群邀请,另一种是借助企业微信生成群活码,不仅可以做到群二维码一直有效,还能做到群满自动新建群。
OSSA 目前是直接使用的严选的企业微信建立的交流群,使用企业微信创建群聊还有一个好处,就是官方提供了合规的群消息发送借口,为在CI/CD过程中向交流群同步一些状态变更提供了可能。
3.1.3 贡献指南(Contributing Guide)
项目开源之后,其他开发者很可能对你的项目感兴趣,想要为你的项目进行贡献,而外部的贡献者又是衡量一个开源项目健康发展的重要指标,所以就需要有一个文档来告诉外部开发者该如何参与到你的项目中。一个好的贡献指南应该包含以下几个部分:
首先需要帮助其他开发者,了解你的项目,能够快速找到相应功能所对应的源代码文件。然后就是如何在本地运行你的项目,以及做了功能更改之后如何进行调试和测试。GitHub 提供了 PR 模版配置的能力,你可以在PR模版中配置一些必填项,来约束PR中所必须包含的信息,开发者在 PR 中提供必要的信息可以为后续的 Code Review 提供极大的方便。比如 OSSA 使用 changesets 来管理版本,理论上所有的PR中都应该包含 changesets 信息,才能在合进主分支时触发正确的版本变更。当你真的维护一个开源项目时,你会发现最让你抓狂的点就是别人提了一个没头没尾的issue,issue中仅包含问题的描述,却不包含具体的使用场景、运行的版本以及环境信息。排查这种问题非常耗费时间,而且极有可能还不能在你的环境下复现。这时候配置一个issue模版,引导开发者提供一些问题复现所必须的信息,甚至直接提供复现demo,可以极大的提升issue解决的速度。
3.1.4 文档及Demo
使用docusarus 建立自己的文档及展示模型。针对前端项目来说,基本上上各个技术栈都会对应的快速建站的框架,目前主流的文档生成框架如下图所示:
3.1.5 行为规范(Code of Conduct)
现在推荐为开源项目添加一份类似“服务条款”的声明,可以自己写,需要包含以下内容:
也可以直接使用统一的范本,你可以直接粘贴一份在你的项目中。在准备完上述要素并且通过公司的开源辅导之后,项目已经具备放到GitHub开源的条件了。在正式开源之前,还有以下两点需要做:目前网易有自己的GitHub Organization,可以选择将自己的项目作为这个Org下的一个新仓库,也可以上传到各个事业部自己的Org或者自建Org。目前 OSSA 选择的是作为严选Org下的一个仓库来进行维护。
项目在开源之前,肯定已经有了大量的commit信息,如果原有commit中包含一些业务相关的信息,建议删除原有的commit信息之后再上传GitHub。如果原有commit信息不涉及到敏感信息,建议保留,因为这些信息可以帮助其他开发者理解功能的演进。
在做完上述各项准备后,你的项目应该已经在GitHub上已经有了一席之地,接下来就是在GitHub上进行项目的迭代和演进。项目的社区维护之路也正式开始。4. 开源社区维护
一个运行正常的开源社区,以下场景应该每天都在上演:- 使用者反馈使用过程中遇到的问题,项目维护者定位问题并给出回复;
- 开发者根据问题列表或者Roadmapzai 提交PR,项目维护者对PR进行Code Review;
作为项目的维护者,除了对项目自身进行功能迭代之外,其他的工作量主要集中在上述场景中。接下来我将以OSSA项目为例介绍如何在上述场景中尽可能减少项目维护者的工作量,OSSA的具体实践仅适用于前端项目,但是其思路可以应用于所有类型的开源项目中。在开始具体思路之前,我们先来了解两个GitHub所提供的能力。他们分别是GitHub actions和 GitHub pages。4.1.1 GitHub Actions
首先,我们先来看下GitHub Actions的能力。GitHub Actions 是GitHub提供的CI/CD 能力,功能类似于gitlab CI。利用GitHub actions 可以定义在某些特殊的时间或者行为节点去触发一系列的操作。GitHub actions相比其他CI/CD工具,最好用的地方在于他提供了actions的官方市场,用户可以上传自己封装的action,然后使用方可以在自己的action中直接引用已经存在的action。目前官方市场上有很多很有意思的action,比如自动同步GitHub仓库的更新到gitee仓库、自动为第一次参与贡献的开发者发一句欢迎语等。4.1.2 GitHub Pages
GitHub pages 是官方提供的一个免费的静态资源托管服务。如果你的项目有单独的介绍网站或者文档,可以很方便的直接托管在GitHub上。其提供了两种使用方式,第一种是搭配GitHub actions一起使用,在GitHub actions中引用官方提供的actions/deploy-pages action,这样就可以在任意可以触发GitHub actions的节点部署你的页面。第二种是从特定的分支进行部署,一般情况下会新建一个gp-pages分支,当源代码合并到主分支时,触发打包编译,然后把制品当作更新在gp-pages分支上提交,每次提交都会触发GitHub pages从该分支上拉取最新的制品进行部署。Issue的工作量主要在定位和解决issue上,在这方面,自动化流程并不能帮多大的忙,但是正如上面提到的,你可以通过创建issue 模版,强制开发者提供必要的信息,来减少定位问题的成本。为issue打上特定的tag,可以方便其他人快速从历史issue中找到对自己有帮助的信息,为issue打上tag这一步骤,我们可以通过GitHub actions进行自动化,官方市场上已经有不止一个解决方案可供选择。目前OSSA的issue还不是很活跃,所以当下我们还没有使用issue相关的actions。但是官方市场上的一些开脑洞的actions却给我提供了灵感,比如TODO to Issue这个action可以收集代码中的TODO,把TODO转换成issue进行跟踪。因为大家遇到问题时,一般都会在GitHub 的issue中搜索解决方案,所以我们其实可以把和代码相关的一些说明性的东西,通过特定方式注释在代码中,借助GitHub actions自动转成issue,在issue中提供源文件链接,这样可以极大的方便用户使用。以OSSA为例,OSSA 项目目前包含OSSA组件库、OSSA组件库的Demo以及OSSA组件库的文档三个部分。如果不借助一些自动化流程,那么当其他开发者发起一个PR时,我需要把这个PR的更改同步到我本地,首先在本地跑起来看下表现是否符合预期,然后再去 review 改动的代码是否符合规范以及是否有更好的解决方案,然后再在本地跑一遍测试确认测试用例全部通过。上述流程中只有review代码逻辑才是核心的工作,其他工作完全可以自动化处理。4.3.1 自动部署
如果当一个PR被创建时,能够自动用PR中的代码进行部署,然后提供到一个部署后的预览链接,那么只需要直接打开这个链接就可以知道改动的表现否符合预期。上述流程理想情况下是使用GitHub actions搭配GitHub pages完成,但是由于GitHub actions的安全策略,想要从fork仓库提交的PR自动部署在GitHub pages上比较麻烦,又加上OSSA有文档和demo两个独立的静态资源需要部署,所以我们选择了部署体验更好,功能更强大的vercel来做OSSA的部署。使用vercel部署GitHub上开源的资源之需要两步,第一在GitHub的项目中启用vercel app,启用过程十分简单,之需要给这个app授权就可以了。第二步,注册vercel账号,并在vercel中新建项目,并配置项目地址、项目打包命令以及项目制品输出目录。然后就完成了所有的配置,接下来vercel会自动托管项目的部署,当合并主分支时,vercel会自动部署线上环境,当在其他分支上提交代码或者提交PR时,会自动把这些改动部署在测试分支,并直接在改动上评论预览地址。效果如下图所示。vercel的部署体验已经做到了极致,不过在国内使用时,会遇到部署的预览地址vercel.app域名被墙的问题。目前官方给的解决方案是,使用自己的自定义域名,然后把自定义域名 cname 到vercel专门为国内提供的dns解析域名上,再把自定义域名配置在vercel后台,vercel会自动把你的自定义域名和你的项目对应起来。需要说明的是,现在自定义域名仅支持主分支对应的环境,PR分支部署的预览域名默认还是vercel.app,如果想要也支持自定义域名,需要充钱,充了钱才能变得更强~4.3.2 自动测试
每当GitHub pages或者vercel部署完成时,都会触发GitHub actions中的deployment_status发生变化。既然GitHub actions可以感知到部署完成,那么只需要配置一个当deployment_status为success时触发的action,我们就可以在这个action中完成项目的测试工作。具体的测试步骤取决于所使用的测试框架,测试框架所生成的测试报告可以使用Publish Test Results来评论到相应的改动中。经过上述的自动部署和自动测试之后,就可以在GitHub的页面上直接直接看到改动之后的页面表现和测试用例执行情况。项目的维护者可以把更多的精力投入到review代码改动中去。一个健康的开源社区,应该会定期发布新的版本,不同技术栈所需要发布的制品及平台不同,前端项目通常需要发布一个npm包。因为OSSA整个项目是monorepo架构,为了自动化管理多包的版本,我们在项目支出选择了changesets解决方案。changesets开源了一个产品矩阵,覆盖了多包项目从开发到发布的各个阶段。4.4.1 版本描述文件创建
相比其他根据commit信息进行自动版本升级的方案,changesets方案需要开发者在提交改动时,同时提交一个这次改动对各个包版本影响的描述文件,描述文件包含了这次改动被合并时,各个包所应该升级的版本。该描述文件既可以通过changesets提供的交互式命令行工具自动生成,也可以直接手动创建。4.4.2 版本描述文件检查
虽然生成版本描述文件的步骤并不复杂,但是相比传统项目,确实是多了一个步骤,所以很多开发者在提交PR的时候会忘记生成版本描述文件。为了保证PR中包含描述文件,changesets提供了一个检查版本描述文件是否存在的GitHub app,只需要在项目中启用之后,如果开发者提交的PR不包含版本描述文件,changsets会自动评论PR,提示缺少描述文件。4.4.3 版本发布
上面所说的版本更新,还都是项目内的版本描述文件的更新,想要真正的更新npm包,还需要把制品上传到npm仓库中。changesets提供了一个版本发布的action,其工作的大致流程如下:理论上所有修改都应该以PR的形式合并到主分支,当PR被approve之后,就可以将这个分支合并到main分支上。当main分支有新的提交时,changesets会去检查提交中是否包含changesets信息,如果包含changesets信息,则根据changesets信息自动更新包版本,并将修改提交到release上,同时新建一个release的PR。在本次版本发布之前,步骤1和步骤2可以针对不同的PR进行多次。等到需要发版本的时候,手动合并之前自动创建的版本release的PR到main分支,此时changesets能够检测到项目办吧的变更,会开始真正的版本发布流程。对OSSA来说,主要包括发布npm包、根据版本新建GitHub tags、根据changesets生成release note并新增GitHub release。
5. 写在最后
以上仅是 OSSA 现阶段对开源的经验总结,GitHub是个宝藏,里面有很多有趣的idea,期待你也能参与其中,感受别人创造的有趣的事物,自己创造有趣的事物让别人感受。