7

前不久,Answer.dev 创始人 @Joyqi 受到邀请,在刚刚结束的 GitHub Universe 的 Local Party 上做了题为「用 GitHub 构建开源项目的各种姿势」的主题分享。以下为他的分享实录。

Hello 大家好,我是 Joyqi。

刚有同学提问,很多学生在大学期间怎样参与开源项目,怎样做自己的第一个开源项目。我的开源生涯也是从大学时间开始,稍后我会分享一下我的开源历程。其实开源可以有不同的姿势,不一定是你去一家公司里面参与开源项目,也可以通过其他方式开始。

先从技术的角度自我介绍一下,我自 2006 年开始参与开源,因为我 2007 年毕业,所以其实大学时就已开始做开源项目。那时全世界的开源运动还处于兴起的阶段,中国的开源项目也应该是第一批,所以当时我算是挺有幸能参与到开源的世界。

image.png

下面是当时的一些开源平台,有些如果你在互联网待的时间比较长的话,会知道这些平台。在 GitHub 之前就有这种开源平台,最早叫 SourceFroge,如果知道那你们够 「老」 的。后面是 Google Code,不过很遗憾,他们做了一段时间且在 GitHub 起来后就不做了。这两个前面应该都是用 SVN,即在 Git 之前的版本管理工具都用 SVN 来做的。我自己本身的技术栈、服务端、前端移动端其实都做过,所谓全栈工程师,其实就是全干,因为之前从事的工作岗位要求我做这些工作,所以我对技术上是很开放的。我自己的开源项目也是各种端都有,我觉得开源是一件挺好玩的事情。

个人开源:用得好所以开源了

说到参与开源的各种姿势,先从最普通的姿势,即大家很多同学或朋友最能接受的一个开源姿势 —— 用得好所以开源了。

这是我的一个小的个人项目,用着比较开心,那它是一个什么项目呢?——给你的身份证图片打码。

image.png

我们现在经常要在一些平台做验证,需要上传证件照,但又不放心,就会在上面打码,比如会打上「仅供用于某些身份验证」这种透明的码。当然如果我们用一些网站的 online 项目,其实也会不放心,因为要把我们的图片传上去,相当于把身份证也传上去了,其实更不放心。所以说我就做了一个这样的项目。

这很简单,前端的同学应该知道,我当时在学 CoffeeScript,半天时间就搞定了。代码其实也只有一两百行,它没有任何网络请求,全部用 canvas 去做图片,然后在图片上写上一行字,可以调整间距及颜色,还有透明度。

当初这个简单的功能并没有做宣传,只在群里面发了一下,后面就不断有人去 star 去 fork, 这个项目的 fork 数和 star 数的比例还挺高,别看 star 仅不到 300 个,但 fork 却相当多,有很多人拿这个简单的项目去实现自己的打码平台,我觉得还挺好玩的。

之所以提这个项目,就是因为做开源的初心。我做开源的初心是先解决自己个人的真实痛点,这个痛点是存在的,是我自己想去解决的,且这个痛点对其他人也特别适用。因为我觉得在互联网上普遍存在隐私泄露的风险,而大家都有这种担心,所以我把它做出来后,尽管周期很短,但依旧会有这么多人关注,有这么多人用,还有很多人提意见,包括有人还给我提 PR 等,这是个好现象。所以,我觉得这种项目对于很多人来说其实难度不大,你们可以去尝试去做一下这种项目。

另一个项目也挺有意思,我把它取名叫「闪光时刻」。

image.png

很多程序学员都会有突发奇想,即突然觉得我有个想法特别牛,其他人都没实现过,我想把它给做出来。然后当时我就写了一个这样的项目——Mobile Device JS ,我们知道 WebGL 有个接口,它可以读取我们显卡的信息,比如像 iPhone ,它就可以通过其接口读取你手机的显卡/处理器 A1 还是 A12 或是 A13 的信息。将处理器信息读取后,根据分辨率就可以很精确地判断你的机器属于哪一代 iPhone,可精确的判断到底是属于哪个型号的 iPhone,这对很多特殊行业有很大帮助。比如网游等行业,这是我后来了解到的,但是当时我只是觉得这个东西很有趣,我突然发现了这样的用法,就把它做出来了。

image.png

对此,我还写了一篇文章发在了 SegmentFault 上,文章的题目叫 「思路清奇:XXXX」,当时挺多人给我评论,挺有趣的。后来有个开发者加我微信,啥话不说先发红包,我从来没见过这种情况。有的同学会给自己的开源项目设立赞助通道,大家会去赞助平台去赞助,但我从没见过有人上来直接给红包的。我当时跟他聊了一下,他说他们是一个比较特殊的行业,这个产品给他们解决了一个很大的问题 —— 原来他们一直想很精确的判断用户的手机到底是什么型号,不能只判断 iPhone 和安卓,必须得判断是哪一代机型,所以说他觉得我的产品对他特别有帮助,我觉得特别有成就感。当然,我的产品给他带来的价值其实肯定不止这些钱,但我依旧觉得挺高兴的。我觉得这是一个特别特殊的经历,可以给大家分享一下,所以说开源其实还是可以创造价值的。

image.png

开源还有一种姿势,有很多的朋友自己从编码习惯出发做开源,这其实是一种「偷懒」。我自己就做了一个这样项目,这个项目刚做还没有什么 star 和 contributor,它就是一个 GitHub 的模板,比如说你有段时间经常想做一类项目,可以把它做成一个模板。然后你可以做一类项目的时候,用这个模板发布项目就可以省很多事。最近我写了很多这种 TS 的项目,就是用 TS 发到 npm 上去,但发现很多动作都是重复的。因此,我看到 GitHub 有这样的模板功能,便在模板里面写了一个 GitHub Action 后,它可以根据你的初始化条目,等初始化项目以后,就可以得到一个标准的 TS 的一个脚手架的项目,在里面直接写代码就可以,很多东西都不用去配,tsconfig 可以不用去配置。以上就是我从个人角度出发的项目。

其实,该类项目不仅仅是上面所说的模板项目,其实还有很多,比如很多人之前会将 vim 的配置作为一个开源项目。如果大家用 vim 的话,应该会关注这种项目或者 VS Code 的配置或者是诸如此类的这种项目还有脚本,我们可以提升平时开发效率的一些项目,也可以做开源项目,这是我个人的一些开发项目及怎样去参与这些开源项目的经验。

很多项目会有一些 star,有的没有 star 或是刚发布出来也没有关注。但我认为追求 star 并不重要,首先是开源的态度,能把东西做出来,把文档写好,对其他人有帮助,我觉得能做到这个态度是特别重要的

社区开源:玩大一点

后面可以玩一点高级的开源姿势,我可以把它叫社区开源。

这是「中国开源码力榜」,一个网站,这是我们和开源社以及 OpenDigger 合作的项目。OpenDigger 负责把 GitHub 上最优秀、协作影响力最大的 100 位中国程序员找出来,然后我们再把程序员的 profile 放到 GitHub 上,去做成一个 Repo,然后这些程序员可以来 fork 该 Repo,更新 profile。我们整个项目就完全托管在 GitHub 上,这是完全社区的项目。所以如果你在这个榜单中,就可以 fork 这个项目,然后去提 PR 跟进你的 profile, 然后我们后面写了一堆 Actions 会自动 build 这个网站,会更新你的 profile。

image.png

大家可以看到,该项目的 PR 其实就是很多人在去更新自己的 profile,然后去增加自己的项目经验。右边我们的 Actions 会去做构建然后发布。我们这个项目是全自动运行的。因为当时我们目标是不想把项目做成一个动态的网站,后面有数据库,我觉得那个太不酷了,太老了,我们把它做成一个完全公开的,所有的数据、所有的构建过程都以社区化的方式运行。所以,我们就选择了这样的方式来做这个项目。

image.png

然后,就是我人生中比较重要的一个项目——我在 2007 年的时候开始做了这个项目,叫 Typecho这个项目现在有 9000 多 star ,从 2007 年做到现在,想想已经有 15 年了,很不可思议,生命力已经出乎了我的意料。创业以后,我工作比较忙,更新的频次很低,在我们 Typecho 的用户群里面,流行一个梗,就是「Typecho 什么时候更新」。这个梗,在我去参加用户聚会的时候,大家经常就会拿出来问。因为更新实在太慢,人家都是以月以周为节点更新,我们则是以年为节点来计算更新时间,但我们其实只是大版本没有更新, commit 还是在经常更新的。

image.png

Typecho 项目其实特别纯粹,特别理想化。大学时我就想做一个中国的 WordPress, 因为 WordPress 当时也在 0.1,我跟他当时基本上是同时间发布的这个版本。然后我就想做一个中国的博客软件出来,也是 PHP 的,因为当时在大学里面接触的第一门动态脚本语言就是 PHP。我们在做的过程中,遇到了当时在中国开的第一个 WordCamp, 一个面向 WordPress 开发者和爱好者的聚会,因此我就认识了我的很多团队成员,他们对 Typecho 这个项目很有兴趣,想来参与这个项目。所以我们 2007 年的时候就以完全远程的方式组建了一个这个社区化的开源团队。

大家都来自天南海北,我们都当时就用邮件列表去做沟通,项目管理也是用 GitHub 的 issue 来做。这么多年下来,该项目之所以还有如此强的生命力,这也跟我们当初选择社区化运作分不开。尽管有的人可能比较忙,没时间更新,但 Typecho 依旧社区运作的项目,大家也可以去提交 PR,可以去提交 issue,也可以去参与到项目中,所以我觉得这个项目可以持续到现在是有原因的。

在该项目的成长过程中,遇到了很多有意思的事,我不知道大家知不知道 PHP 这个语言,其实它分很多版本,每个版本又可以部署在不同的平台上,然后部署的平台上又可以有很多不同的部署方式。所以后面我们每天有一个 nightly 版本,每晚会编译该版本。但编译环境特别复杂,即多版本多操作、多环境、多 CPU 架构交叉定义。

image.png

GitHub 有一个好处,就是 GitHub Actions Runner 对开源项目是完全免费的。所以尽管编译特别耗时(每天晚上编译一次大概需要三个半小时),如果让我们自己机器去编译的话,这个是很费钱的。但用 GitHub Runner 来做的话,我觉得还是薅到了很多「羊毛」。最早的时候是所有平台全部并行全部并发的去编译,编译的时候直接把 runner 给搞挂了(不知道是我搞挂了还是它自己本身有问题),所以我们后来换了一下,每个平台会有一个 stage, 编译完以后进入到下一个平台,也相当于做了一个小小的分发,这是我们这个项目比较特殊的一点。

还有一点,就是我们的项目用到了比较多的 GitHub 交叉。GitHub Actions 有 API,我们会在 GitHub 多个项目之间,因为整个 Typecho 项目下面会有多个 Repo,比如说有 Typecho 这个 Repo 它是用来放项目主要代码的,Languages 这个 Repo 是用来放所有的多语言的,大家可以看到现大概 17 种语言的都是用户去提交,然后这两个 Repo 之间其实是有联动关系的,做了一个相互交叉的 Trigger。

image.png

如果 Typecho 这边修改了某一些语句的话,它会 Trigger 到 Typecho Languages 项目,Languages 项目编译自动把 Typecho 项目的代码 clone 下来,然后去编译 message.bot 这文件,发布语言包,之后 Typecho 再从该项目里下载语言包编译成一个多语言版本的 Typecho,这实际上是多方触发的关系,我们把它用 GitHub Actions 做了个实现,这样就可以减少很多手动过程,由于我们本身人就少,人工特别金贵,因此尽量都自动化。

以上就是 Typecho 的情况。

公司开源:技术能力溢出

由于我们自己在 SegmentFault 也开源了很多自己用到的组件,所以如果公司要做开源项目,或公司的某个产品要去开源,我觉得这是很多国内大厂经常用到的一种开源模式,更多的是来自公司的能力的溢出。

如果你做了一个项目,但由于该项目只能在公司内部用,所以会觉得自己的能力被埋没了,或是自己的影响力应该可以覆盖到更远的地方,所以此时你就该将它开源出来。公司开源的项目有几个特点

  • 把项目开源出来肯定是来自公司项目的能力溢出 —— 因为你的公司能力,你能达到这个地步,你才会去开源这个项目,所以可能只有优秀的公司才有能力去做开源或做成功的开源。
  • 它是以公司的技术团队为主体的,就像我们这些项目可能现在还没有做社区化,只是一起提 issue 或修小的 bug 提一下 PR,但主要还是以我们公司的团队为主,因为是我们主动将其开源出来的。
  • 另外就是这里面重复造轮子的事情会比较多,下面两个例子就是有点吐槽的意味:比如现在看不少大厂的开源项目有很多重复的轮子,早前前端行业里被吐槽比较多,mix 还有前端很多渲染的项目,都会重复造很多轮子。
  • 为什么?我觉得可能就是因为在大厂内部有很多能力需要去释放,可能受到 KPI 影响,所以会重复造轮子,给后面长远发展造成了影响,有「人走茶凉」的风险。如果团队有调整的话,该项目就会因为没有人维护而被「搁浅」。这也是为什么我们之前用开源,如果没有基金会维护,只是一个厂商去开源的项目,我们会有这样的疑虑 —— 他会否有可能过段时间就不维护了?

image.png

我们在做功能的时候,就遇到了刚与 GitLab 的同学一直在聊的这个问题 —— 社区与内部同步。因为这个项目是从公司内部开源出来的,所以它肯定是在公司内部的代码托管平台先做了开发,然后再放到 GitHub 上去。它的开发主体可能还是在内部,只是它会定期地去 push 到外面的 GitHub 的 Repo 上去。因此,这就会存在同步问题。

该问题我们目前已经有了一些解决方法,但也不能说完全解决了 —— 因为存在一些代码的同步问题。

  • 目前,我们在代码同步方面采用镜像的方式,就是 GitLab Mirror 到 GitHub 上去。但这有一个问题,如果你在 GitHub 上有 PR 的话,merge 就会有很大的问题。
  • 所以我们现在也不用 Mirror 的方式了,而是两边分开,会有机器人去做同步,如果那边 GitHub 有 merge 的话,它就会同步到 GitLab 里面, PR 管理也是这样,它有一个 webhook,如果那边有 PR 的话,我们就不会接收这个同步的信号,而是将其同步到内部的代码里面。
  • 分支里我们用了一些比较常用的 Flow ,之前用的是 Git Flow ,现在则不常用 。
  • 在这里,为什么要强调说一下 CI/CD 呢?就像之前所说,如果将其放 GitHub 上,它的 runner 的计算能力是有限制的,除非买付费 plan,不然其 build 能力是受限的。所以,现在将 build 部分放在我们自己的内部平台里面打包编译,然后社区只做测试,跑单元测试代码或是去做比较轻量的一些计算。

以上就是我们内部和外部的代码管理平台的一些经验。

做了这么多个人开源项目、公司的开源项目以及社区的开源项目之后,我们就开始思考一个事情,我们能不能将开源这件事情做成一家公司,将公司做成一个开源公司,把我们自己的能力充分展现,把我们主要产品的能力开源出来。

image.png

有了以上积累,我们做了开源问答社区软件 Answer,该项目正式发布于 10.24发布后的第一个星期,就在 GitHub Tending 霸榜了一周左右,不到一个月时间已有 4000 多 star。正因为 SegmentFault 是做问答社区起家的,所以我们积累了大部分问答社区的经验。在我们做社区的过程中,有很多 B 端的用户提到他们也需要这样的社区,能不能帮他们搭这样的社区,或是怎样去实现这样的社区。之前我们很难去响应这种需求,只能提议他来我们社区建一个专区或子站,但我觉得这样的话他们的需求不能完全满足,因为他们有些内容是需要完全自定义的或自己去控制自己的数据。

基于这样的想法,也基于我们在社区开源这么多年的思考,我们在想能不能把我们在问答社区领域的能力完全开放出来,变成一个开源的项目让大家来用。这样其实是颠覆了我们整个商业模式 —— 之前我们就是一个社区公司,通过广告服务来赚钱。如今,我们变成了一家开源商业公司,一家软件公司,我们的驱动力也变成了用社区驱动来开发,跟我们此前的驱动方式完全不一样。

但我觉得开源对商业公司来说是至关重要的,正如刚才有人问韩骏老师是否有想法将开源项目做商业化的时候,我们也在想这个问题 —— 开源带给商业化最大的一个作用是什么?其实对商业用户来说,建立信任是很重要的步骤,为什么让用户相信你去买你的产品?你可以想象一下,为什么我们要付费买 GitLab ?如果你的公司足够大,可以支持买 GitLab 这样产品的话,你为什么心甘情愿掏钱买?或者你买 JetBrians 这种编辑器的理由是什么?为什么?因为你用过它的开源产品,你知道它的代码,你知道它整个运作流程,你相信它有一个坚持的社区在支撑着这一切的运作,它有着很健壮的力量。对我们软件开发者而言,健壮性是很必要的一个条件。如果你只是一个小作坊或小公司的话,我很难把自己内部的能力展现给你。但如果开源的话,我可以把我对社区的管理能力统统展现给你。我觉得这对商业化来说是很重要的一步,用户可以通过这个过程来相信你的产品,相信你的产品可以给他们带来价值,也相信你可以很好地去发展这个产品。因为他不可能就用一次,肯定要长期去用的。所以,这也是当时我们要做开源公司的最初的思考。

具体到开源公司后面怎么去做商业化、商业模式,我们想得比较多的就是软件 SaaS 方面了,后面我们可能会围绕这样的能力来去构建商业化产品。以开源模式做公司的话我们会有会遇到一些转变,首先就是国际化

image.png

由于我们的项目是完全国际化的项目,其文档全是英文,发布渠道也是在国际渠道,所以它给我们带来了很多思维上的转变。之前我们没有过多地思考这些问题的,但我可以分享出来,大家可以借鉴一下,我们现在也还在处理这些问题当中,比如我们的文档、注释都是全英文。这一点之前我们可能有些人没有写注释的习惯,或是写文档的习惯,对他来说是一件很难的事情。但如果你要做一个社区,这两样都是特别重要,特别是对一个国际化产品而言,全英文的文档,是用户了解你的第一步。

我们也把英语作为社区的官方语言,现在也有很多中文用户来提问,我们不会拒绝,但我们会引导大家尽量用英文去提问。

现在,我们在做的一步是将语言档剥离,然后交给社区去维护。我们现在把它交给到第三方的开源平台,大家可以在上面帮我们翻译一些词条,目前已经有一些翻译了。

接下来,就是社区化的过程。

image.png

其实刚刚也提到过,我们现在的产品路线图已是完全社区化了,现在用 GitHub 的 Project 来做路径图,用 GitHub 的 Project 来发布这些功能,或是参与讨论这些功能,或是它已经实现的功能我们都放在上面。然后告诉大家我们会在哪一个阶段完成,比如 Q1、Q2、Q3、Q4,或者还要标注它是哪个版本,比如在 0.3、0.4 哪个版本发布。在这个过程中,这些功能你都可以参与讨论。如果你还有其他的功能建议,也可以在 issue 里面提出来。提出来后,我们觉得合适的话会把它列入到我们的 Roadmap 里,这些过程全部是公开的,大家可以在里面自由讨论自己想要的功能。

还有一个就是我们的社区,现在除了传统社区如 GitHub 社区及 Stack Overflow 等其他类似的社区以外,我们还在一些比较新的国外社区做推广及社区建设,在上面也可以讨论我们的产品,我们在 Reddit 上有频道,在 Product Hunt 上也发布了,当时也收获了特别好的反响和回馈,我们还建立了 Discord 聊天频道,大家可以在里面聊我们的产品,和我们官方沟通。

image.png

最后,聊一下在 Answer 项目里遇到的一些挑战:

第一,就是文档。刚才也说了,文档对我们很重要,因为之前没有受过这种专业的文档训练,所以我觉得这个课我们必须补上。现在我们实际上是在集体学习怎样编写一份好的文档,包括文档结构,描述性的语言,包括它的排版。目前都在疯狂的学习当中,现在还没有做到足够好,但我们的态度是一定要编写一份能让大家、能让开发者或用户阅读起来很舒心的一份文档。

第二,就是社区答复时间和工作时间的分配。这是项目发布以后我们遇到的一个比较大的问题,用户的问题会集中一段时间在上面提出来,我们要解决的话得要 Debug 复现他的问题,要跟他讨论,很费时间,所以该如何平衡这个时间呢?如果所有工程师都在花时间在这里解决这些问题的话,很可能会影响到我们正常的产品开发。
因此,我们现在有一个定期轮值的机制,即前端或后端会分出一个人力来在一段时间重点跟踪这些项目,他的时间会分配得比较多,使得其他人在社区答复上面受到的影响少一点,以此来做正常的项目迭代。这是我们目前的一个做法,还在调整中,后面如果还有更好的解决方式的话大家也可以去讨论。

第三,如何将产品和技术理念国际化。现在我用中文跟大家交流,但如果在更广阔的国际平台上用英语,就是用或写文章或是做演讲的话,对我们自己的语言能力是一个挑战。很多人之前没有重视这方面,但我觉得这是让其他用户对你的项目产生信任的很重要的一步。可以通过这些了解你对产品的态度很重要。

第四,就是社区的规则。这一点我们现在还在建立中,包括怎样奖励对我们贡献比较大的人,我们希望建立成一种规则性的东西 —— 比如:你对我们产品有很大的贡献,我们有实物的奖励或给你有一些荣誉;如果你的贡献足够大,你又有兴趣比较全职性的参与进来的话,我们会给你怎样的身份来将你吸纳进来。还有就是大家怎样参与到项目方向性的讨论中来,这是我们后面社区要去建立规则的一个重点。现在的讨论还比较分散,但我希望我们能有一些定期的话题去讨论,讨论完后可以形成某些提案,大家可以去投票,去决定做不做,很多成熟的基金会是有这样的机制的。

image.png

最后是我们项目的一个小广告,大家如果想贡献的话,可以一起来贡献,不管什么形式,哪怕是言语上的鼓励也可以。

https://answer.dev
https://github.com/answerdev/answer
https://twitter.com/AnswerDev

这是我们的官网主页,包括我们 GitHub 主页及我们在 Twitter 的官方账号,欢迎大家随时与我们互动。

我的 ID 是 @joyqi,大家可以在各个平台都可以通过该 ID 搜到我,欢迎大家和我联系!


ApacheAnswer
101 声望39 粉丝

开源问答社区软件 Answer.dev 官方账号