文章目录
  1. 1. 起步
  2. 2. 进阶
    1. 2.1. Issue
    2. 2.2. PR
  3. 3. 技巧
    1. 3.1. 问题导向的源码阅读
    2. 3.2. 友善的互吹评价
    3. 3.3. 有效的沟通
      1. 3.3.1. 提问式的反驳
      2. 3.3.2. 注意描述方式
      3. 3.3.3. 模板与工具
  4. 4. 总结

【开源社区贡献者】听起来是个专属于顶级开发者的头衔,但它真的有这么遥不可及吗?下面的分享旨在揭开它的神秘面纱,帮助感兴趣的同学更轻松地参与到社区项目中来。

首先需要澄清的是,本文作者自己并不是社区高大上项目的原创作者,只是在一个 5k+ Star,100+ 贡献者的项目中贡献排名前十而已(作为参考,Vue 的贡献者不到 150 人),和《维护一个大型开源项目是怎样的体验》这个问题里闪耀的群星相比,只不过是个小透明的存在。不过因为自己也只有一年有余的经验,在很多方面上和刚刚入门的新人同学们都很相似,因此相信个人经验能有一定的参考价值,才在此做了些总结。文中如有不妥之处,请 dalao 们斧正。

下文内容主要分为这两部分:

  • 起步与进阶,介绍在对编程一无所知的时候,能够通过什么方式参与到社区中来。以及在有了贡献的条件后,如何通过 Issue 和 PR 在开源项目中协作。
  • 技巧与总结,介绍一些技术性的细节,以及如何在 Github 上商业互吹的沟通技巧。

起步

参与开源项目的主要方式,由易到难不外乎这三种:

  • 翻译文档
  • 报告 bug
  • 提交代码

在起步阶段,翻译文档的难度无疑是最低的。因为这甚至不需要你编写或运行任何代码,只要在编辑页面里翻译就足够了。

以 Mozilla 维护的 MDN 文档为例,也许有不少同学不知道,MDN 文档和维基百科一样,是允许所有用户编辑的。比如,一篇介绍 CSS 定位方式的 MDN 文档,页面顶部大概长这样:

mdn-large

注意到 LanguagesEdit 了吗?你可以在 Languages 里选择你需要的语言,或者添加新语言的翻译。如果已有翻译,可以直接点击 Edit 编辑!

在翻译时,Mozilla 的富文本编辑器会分为左右两个部分,可以直接对照:

mdn-editor

现在只要点击保存,你就会出现在这个页面的贡献者里了!你的更改也会在文档历史中保存,所以在提交前不妨检查下内容吧。另外,并不是一次保存就必须搞定一整篇文档,写到一半准备保存的话,可以点击页面最下方的 本地化进行中 选项,这样就能够在浏览页面中添加一个【翻译正在进行中】的标识啦。

这个过程里我们似乎一行代码都没有写,那么这有什么用吗?个人的观点是,翻译文档是一个很好的开始,因为它可以:

  • 帮助你更好地理解英文技术文档的行文结构,为后面和其他开发者的交流打好基础。后面我们也会提及,很多时候需要为一两行代码编写的文档远远不止一两行。
  • 很大地锻炼你的行文水平。在初期你可能会写出比较翻译腔、不通顺的技术文档,熟悉以后会有很大的进步。
  • 让你的贡献迅速地得到反馈。MDN 的权重在 Google 并不低,通过 Google 在第一页查到你翻译的内容,还是挺有成就感的。
  • 提高你自己对文档内容的了解。以作者本人为例,在了解富文本编辑领域时首先就是从搬运 Mozilla 中的富文本编辑器文档作为开始,完成翻译后就这个领域内的基础概念了然于心了。

除了 MDN 文档外,中文技术社区也有不少优秀的相关项目可以参与。这方面个人的参与不多,就不班门弄斧了。

进阶

只是翻译文档的话,你可能很快就会达到【写腻了】的阶段,这时候就不妨来看看更大的世界吧。找一个 Github 上的活跃项目作为开始吧!对于在 Github 上维护的开源项目,主要的参与方式包括 Issue 和 PR 两种:

Issue

对一个中大规模的开源项目,Issue 主要用来:

  • 报告 Bug 与提问
  • 提出并讨论新特性
  • 设定 Todo 目标

需要注意的是,许多项目是有自己的 Discuz 论坛或 Slack 群的,有一些类似【为什么安装失败了】的新手向问题可以先在已有 Issue 中搜索,然后再在论坛和 IM 中提出。如果随意地提出 Issue,很可能会得到 Duplicate of #xxx 的回复然后被关掉。对于新同学,一个非常好的参考是《提问的艺术:如何快速获得答案》

只要给项目提出过 Issue,你当天的 Github 贡献图就会刷绿,并且也能够把这个项目固定在个人主页里了!看起来同样不需要写代码,并不难呀。不过,单纯地提 Issue 并不会让你出现在项目的贡献者列表里,如果想真正地【贡献】代码的话,PR 是必须的。

PR

Pull Request 顾名思义,就是请求别人拉取你的代码的意思。这是十分符合开源工作流的:开发者们 fork 出自己的仓库,在自己的 分支里 commit 代码,然后请求维护者将自己的更改合并进来。一般而言一个 PR 只要做好一件事情就足够了,其作用不外乎以下之一:

  • 修复 bug
  • 实现新特性
  • 优化性能
  • 例行更新(如文档、依赖版本等)

新同学如果想要贡献 PR,不妨先从自己擅长或关注的方面去着手,比如一些简单的文档拼写错误,或者标记为 help please 一类的 Issue。

只要提出 PR,不论合并与否当天的 Github 贡献图都会刷绿,而 PR 合并入主干时,当天的贡献图也会刷绿。假设你发现了一个小 bug,只要一行就能够修复,那么整个流程走下来大概是这样:

  1. 提出 Issue,贡献 +1
  2. 提出 PR,贡献 +1
  3. 回复维护者的 Review 评审,贡献 +1
  4. PR 通过,贡献 +1

所以,哪怕仅仅提交一行代码,最多也足够点绿四天的贡献图了。并且,维护者们在 Review 或并入你的 PR 时,他们的贡献也会相应增加。这样想来,大型项目贡献者们一年动辄几千的贡献数量也不是只能让人仰望的了吧。

技巧

上面仅仅介绍了开源工作流中的几个基础概念。在真正参与时,还有一些可以稍加注意的技巧。下面介绍的就是一些与此相关的小细节。

问题导向的源码阅读

在需要提出 bugfix、新 feature 或性能优化类 PR 的时候,阅读框架源码基本是绕不开的。当然,我们经常能够在技术社区看到很多【源码解析】类的文章(在近期以 Redux / Vue / Koa 为甚)。作者写这些文章的出发点肯定是好的,不过令人有些遗憾的是,许多这类文章的阅读量相对并不高,并且多数这类文章的作者并不是这些框架的贡献者

是我们太浮躁了吗?我们不妨从动机上考虑一下,我们为什么需要阅读源码呢?是为了解决实际遇到的问题,还是仅仅为了写一篇博客来展示自己的技术水平呢?如果只是贴上一个个看起来高大上的代码截图,然后把注释翻译成中文,这样的文章对读者、对社区又有什么帮助呢?【我读过这个框架的源码】和【我修过这个框架的 bug】相比起来,哪个的贡献更大呢?

个人的观点是,带着问题去调试源码,收获会比简单的阅读理解大很多。在你真正需要解决一个 bug 的时候,你才会真正去思考调用的顺序、执行的流程、变量的意义,然后在一个个断点、日志和错误堆栈的帮助下,真正知道一些看起来漫不经心的判断是多么不可或缺,看似简单的地方又隐藏着怎样的预设条件。

从这个角度而言,以修复 bug 的动机驱动去维护开源项目,对技术水平的锻炼,会比在单纯的源码阅读或在技术社区里逛博客点赞要来的更高。而每一个发展中的项目,都会有不少已发现或未发现的 bug 等待我们去修复。在这个参与的过程中,你的工作不仅能让社区收益,也能够更多地让自己获益。

不过,【如何阅读源码】已经脱离了本文的讨论范围。在此我们点到为止就足够了。

友善的互吹评价

参与开源项目和搬运文档相比,很重要的一点区别在于和其他人之间的互动。你的 Issue 会有人评论、代码会有人 Review,PR 也会有人点赞。这时候,和其他人的互动是少不了的。在 Github 这样的英文技术社区,合适的交流方式对促进社区发展是很有帮助的。

这里我们只分享一点:如何更友善地对其他人的工作作出评价。在中文社区,除了【伸手党】以外,还经常能够看到【喷子】直接抨击项目质量或者给人盖上【抄袭】的帽子。不过,吐槽别人的代码肯定是少不了的。在社区中交流时怎么样更委婉地指出 PR 的问题或在 Issue 中回复观点呢?

很有趣的一点是,在 Github 上很少看到这些词:

bad wrong dirty terrible ***...

更基本看不到这样的说法:

I think this code is bad and do things wrong!

与直接吐槽代码 bad 相对地,不妨这么说:

  • 表达 API 笨重不好用,可以说 heavy to work with
  • 表达模块结构不好,可以说 not intuitive
  • 表达处理方式太粗暴,可以说 overkill
  • 表达逻辑可能有漏洞,可以说 leaky
  • 表达要引入的东西太多,可以说 aggressive

I think 则显得非常武断,可以这样:

  • 万能的 IMOIMHO,即 In my (humble) opinion
  • 补充一个 Not sure, maybe missing something
  • To my knowledge 或者 For me

以及,在请求其他贡献者 Review 或合并时,记得加上 Would you pleaseCould you please 也是很不错的。哦对了别忘了 Thanks 啊。

总之探索合适的沟通词汇是一件很有趣的事情,不过对英语的要求并不高,运用上面的介绍其实只要初中英语水平就足够了吧…相信有兴趣的同学能够总结出更多【开源黑话】😅另外,不少项目的 Code of Conduct 也值得一读。

有效的沟通

贡献社区的过程并不是上来就把代码砸到人脸上,许多 bugfix 都是需要和上游维护者讨论方案后再做决定的。这时除了客气的言辞外,沟通的方式也很重要。在此个人总结了这么几点:

提问式的反驳

苏格拉底有种和人辩论的方式是,不停地向对方提问,直到对方答不上来为止。在社区的交流中,这种方式同样很常见。

比如,在认为一个 PR 存在着未考虑到的边界情形时,作为 Reviewer,比起直接判断 You are missing XXX,评论 How is it when XXX 就巧妙地【把锅丢了回去】,能够客气地让提交者进一步说明对特殊情况的判断或修改代码,而不是直接【把天聊死】。

同样地,在不认可某种 Workaround 方式时,回复 I don't know what you mean at... 然后等待对方的解释,效果也比直接说 This is wrong 要更好。

注意描述方式

在提交 Issue 时,不同的描述方式可能会带来不同的优先级与不同的处理结果。举一个最近遇到的例子:

我们参与的项目中,有一个描述【性能问题】的 Issue,内容大致是【输入内容大的时候速度特别慢】。这个 Issue 被晾了一两周没有人处理。而我在调试后找到了一个特殊的场景,这时反复的重绘会让页面崩溃。在将【页面死循环】作为标题提交 Issue 后,作者在当天就修复了这个问题,而性能问题也一并解决了。

模板与工具

其实上面的不少内容是有固定的套路可循的。比如,Issue 和 PR 都有相对固定的模板,帮助参与者提高沟通的效率。

对 Issue 来说,常见的模板大致是这样的三段论:

  1. Bug or Featrure?
  2. Current Behavior?
  3. Expected Behavior?

而对于 PR 来说倒不一定需要长篇大论,正式一些的结构大致是:

  1. This Closes #xxx
  2. Current Behavior / Reason
  3. Solution

在提交 Issue 时,提供复现的例子、步骤或 GIF 是非常重要的。这时我们可以用 JSFiddle 提供简单的复现例子,在 Mac 上也有 Giphy Capture 这样免费的 GIF 动画录制工具来提供帮助。

最后,在 Git 提交时,整洁的提交记录也是很大的加分项,这方面有兴趣的同学不妨参考作者之前的文章:使用 git rebase 提高 PR 质量

总结

参与到开源社区中是个既有挑战也有成就感的事情。比起国内互联网公司常见的招聘 slogan【你的一行代码,能影响多少多少人】来,贡献到开源项目中,就意味着【你的代码能够被多少多少公司】使用,这无疑是更高的层次,也会有更多的挑战。如果觉得日常的增查改删逻辑已经让你感到厌烦,那么参与到社区中来或许能为你打开新世界的大门。

这里顺便安利一下我们目前维护的编辑器项目 Slate。这是一个优秀而迭代迅速的富文本框架,目前还处在大刀阔斧地添加新特性和新功能的 beta 时期,有非常多参与贡献的机会,源码的风格与注释也相当完备。另外有趣的一点是作者和 Evan You 一样有着设计师的背景(不妨想象一堆程序员给 UI 设计师写的代码修 bug 的场景)。我也在之前的博客里安利过 Slate,希望能有更多的同学来尝鲜!

最后我们引用 Chrome V8 项目的一个原则作为本文的总结吧:

In short, do the right thing for the project, not the easiest thing to get code committed, and above all: use your best judgement.

文章目录
  1. 1. 起步
  2. 2. 进阶
    1. 2.1. Issue
    2. 2.2. PR
  3. 3. 技巧
    1. 3.1. 问题导向的源码阅读
    2. 3.2. 友善的互吹评价
    3. 3.3. 有效的沟通
      1. 3.3.1. 提问式的反驳
      2. 3.3.2. 注意描述方式
      3. 3.3.3. 模板与工具
  4. 4. 总结