这次籍着Electron 1.0发布的机会,说说我自己维护两个大型开源项目的经历吧,分别是
node-webkit(也就是现在的NW.js)和
Electron。
前者是几年前自己单打独斗,在公司0资源投入的情况下从两百多star一直做到好几千star,具体数字已经忘掉了,只记得当时在C++项目排行里做到了前十,直到自己另起炉灶。而后者,则是披着GitHub的光环,有着公司热心的投入,毫无障碍一路跑到了现在的三万多star。
(使用
Star History生成的star数统计图)

一切从node-webkit开始如果大家有接触过前端或者桌面端的开发,那么很可能有听说过NW.js的大名,node-webkit就是其改名之前的称呼。
但绝大部分人可能并不知道,node-webkit在最初发布的时候(2011年),并不是面向开发桌面应用程序,而是一个Node.js模块,可以创建一个WebKit窗口。神奇的一点是,你可以在这个窗口的页面里调用Node.js的模块。
Node.js代码:
var nwebkit = require('nwebkit')
nwebkit.init({'url' : 'index.html'}, function () {
nwebkit.context.runScript('')
})
index.html代码:
<html><body>
<p id="output"></p>
<script>
require('fs').readdir('.', function (err, files) {
var result = ''
files.forEach(function (filename) { result += filename + '<br/>' } )
document.getElementById('output').innerHTML = result
});
</script>
</body></html>
大家可以在
NW.js的webkitgtk分支里找到node-webkit的原始实现,甚至尝试重新build一遍。不过这个模块一直未能稳定下来,玩具的味道更多一些。
再后来,原作者
rogerwang对其进行了改进,从使用WebKit改成了调用
Chromium Embedded Framework(简称CEF),一个可以把Chromium嵌入应用程序的库。这个代码一直没有正式公布,但大家可以在
node-webkit的cef分支里找到。代码的另一部分是针对Chromium的几十行补丁,将Chromium的message loop替换为libuv,但是NW.js在开发过程中对代码库进行了很多次rebase操作,原始代码已经找不回来了。
找个实习生来开发node-webkit的原作者rogerwang在Intel开源技术中心工作,虽然Intel在大家心目中可能更多是个卖CPU的,其实在开源方面也非常热心,甚至提供开源方面的实习工作。
在2012年的夏天,
一则Intel的实习信息吸引了我的注意,上面说Intel需要一名熟悉Node.js的学生来进行node-webkit的开发。我投了简历,也很幸运地开始了node-webkit的开发。
Content Shell我最初的工作是对node-webkit的cef分支进行改进,但是很快就发现很难继续进行开发了。CEF提供了自己的一套API来包装Chromium的内部API,而Node.js则是直接调用V8的API,如果想要把CEF和Node.js合并到同一个项目,困难重重。
于是我干脆将node-webkit推倒重写。新的代码基于
Content Shell,一个Chromium代码库内的最小化浏览器实现。
重写后的结果非常不错,我得到了一个可以调用Node.js模块的浏览器实现。基于这套代码我发布了
node-webkit v0.2.1。
把node-webkit进化成桌面开发利器至此node-webkit已经变成了一个独立的浏览器,而不再是Node.js模块。为什么不把它变成一个使用JavaScript和HTML开发桌面应用的工具呢?后面几个月我开始对这个想法进行尝试。
首先我模仿游戏框架
LÖVE framework为node-webkit实现了一个打包系统,可以把应用直接附加到exe上:
(node-webkit的打包系统,来自
我自己的PPT)

这个打包系统一直沿用到NW.js,但是因为性能方面的种种原因,后来在开发Electron时我并没有使用这套系统。
接着这是各种细节上的完善:比如利用package.json文件来描述应用;给窗口加工具栏;拓展DOM来提供API;取消浏览器的安全系统;等等。当然还有无休无止的bug修复。
其中最有挑战性的一点是支持Node.js的native module,我对Chromium打上各种补丁来暴露V8和OpenSSL的API,给Node.js打补丁好解决OpenSSL和NSS之间的符号冲突,提供自定义的node.lib来支持Windows,最后还要提供适用于node-webkit的编译工具。
完成这些工作以后我发布了
node-webkit v0.2.5。
提供构建GUI的API这时我的绝大部分工作都在围着浏览器转,而由于浏览器自身的局限性很多功能我都没法提供。比方说浏览器里就没法创建系统原生的菜单。(当然今天已经有了HTML5 Menu标签,而当时是2012年。)
于是我想到增加一个新的内置模块,用来提供对窗口、菜单等系统API的绑定,也就是:
如果你有使用过NW.js的话,你应该很熟悉这一套API。
经过几个月的完善后,我发布了
node-webkit v0.3.6,这也是由我维护的最后一个版本。
node-webkit的推广虽然node-webkit属于Intel,但其更多属于rogerwang的个人项目,那时候这个项目在GitHub上也还挂在rogerwang的账户下。所以当时除了我自己一个人,没有其他任何来自Intel的资源投入。
而像node-webkit这样的框架类项目,只有拥有用户,才会有生存下去的意义,所以在开发node-webkit的半年时间里,我也一直有在积极推广。
首先是到处发帖子宣传node-webkit的好处,一大阵地是Node.js的邮件列表。每次有新版本我就会过去
发布公告,回答问题,与人撕逼。其次则是
编写范例应用,让新手快速入门,让其他人相信node-webkit的能力。最后则是
去技术会议宣传,让大家知道node-webkit这个东西。
当然最重要的还是认真回答Issues里的问题,努力修复bug增加功能。
我的努力最后也得到了非常好的回报,在我结束node-webkit开发的时候,项目在GitHub上获得了数千个star,排到了C++项目排行的前十。
第一个用户另外值得一提的是node-webkit的第一个用户,
Light Table editor。这个编辑器的作者
ibdknox很大胆地使用了node-webkit来进行开发,当时为node-webkit迎来了非常多的关注,也给大家吃了一枚定心丸,为项目推广助力巨大。
几年后Light Table又从node-webkit
迁移到了Electron,当时好似好友重逢,感触良多。
工作的转移在我为node-webkit工作半年之后,2012年底,这个项目开始吸引越来越多的注意力,也开始引起Intel一定程度的注意。rogerwang得到了机会放下其他的工作,开始全职维护node-webkit。
(GitHub的代码贡献表)

大家如果有在比较大的公司工作过,之前可能会奇怪,为什么一个实习生能如此随意地修改代码,发布新版本。其实正是因为这个项目当时在Intel内部无人关注,无人管理,我才得以随心所欲地尝试各种想法。
但之后正当node-webkit冉冉升起之时,我却彻底失去了node-webkit的自治权,开始收到命令去完成指定的开发工作,被禁止随意去增加功能,也不允许去随意修复bug,而发布新版本、和客户交流的工作也被转移给更高级别的工程师手上。正如一个大公司里的螺丝钉。
可能这种开发方式才是大公司的常态,我也不想抱怨任何人,但是抱歉,我只是一点也忍不了。
为GitHub而战在我进行node-webkit开发的同时,GitHub正在秘密开发Atom编辑器。我了解到GitHub正在寻求一种使用HTMl和Node.js来开发桌面应用的方式,于是联系到Github
的工程师
nathansobo,表达了为GitHub工作的意愿。
所幸node-webkit已经为我自己博得了足够的名气,在一面未见的情况下,我们敲定了协议,我需要将Atom迁移到node-webkit之上,并且提供支持工作。
于是2012年底,我结束了在Intel的实习,开始为GitHub作为contractor工作。
一个更好的桌面应用框架在我加入Atom的开发时,项目还基于CEF。
我们尝试了将Atom迁移到node-webkit上面,但是最终效果并不是很好,node-webkit当时并不稳定,而且API有太多的坑。
于是我开始重新考虑node-webkit的API设计,发现如果想要支撑大型应用,我不得不做出很多结构性的改变,而这些改变与其修改node-webkit,不如重写更加实际。在和GitHub讨论之后,我开始编写一个新的桌面应用框架,当时的名称叫做atom-shell。
有兴趣的同学可以去了解一下
我们究竟做了哪些改变。
左右互搏后来,经过长时间的开发,atom-shell最终开放了源代码,而与此同时node-webkit 已经吸引了非常多的注意力和用户,我开始了和自己的竞争。
再之后node-webkit改名为NW.js,而atom-shell则改名为Electron。
(Electron 1.0)

维护开源项目的生活说完了从node-webkit到Electron进化的历程,最后说说维护开源项目的体验吧。
和普通项目不同,开源项目几乎所有的用户都来自公司外部,取决于项目的受欢迎程度,每天都会受到相当大数量的邮件。就我自己而言,来自GitHub的通知邮件每天数量在50封左右,需要花1到3小时左右一一消化回复。很多issue要去仔细重现,一些话题也需要大量的讨论,很费神。甚至会有troll过来破坏所有人的心情。
其中最让人无奈的
一个troll,最爱跑到issue下面留言,指摘Electron抄袭NW.js的代码,剽窃NW.js的理念,还到处劝人转用NW.js。简直了。
维护项目的另一项工作,是审核pull request,和维护node-webkit时不同,Electron的用户群要大很多,所以每天都会收到pull request,其中不乏高质量的代码。但多数时候代码都不能直接合并,要么设计不合理,要么代码不合规范,更多地则是引入新bug。所以每个pull request都需要细心查看,还少不了和贡献者大量的讨论。
于是,做完这些工作以后,留给写代码的时候反而少了很多,也是没有办法。但对于一个开源项目而言,这些琐碎的工作其实非常重要,只要让人感觉你的项目在被精心维护,才能不断吸引更多用户。一个维护不善的项目,哪怕初期因为种种原因吸引了很多用户,一旦更好的替代品出现,用户马上会飞速流失。
生活上,因为是全职做开源,影响反而非常小。GitHub的远程工作氛围非常浓厚,我的大部分工作时间也是在家里而不是办公室里,所以多数时候是想写代码了便开始工作,不在状态就把工作放在一边去做做喜欢的事,以此用有限的时间维持非常高的工作效率。
但开源会给自己带来另一个问题,责任感。一个没人用的项目,弃坑不过是一转念的事情,但是当越来越多人开始用你的项目,甚至有
创业公司把未来压在你的项目上,责任感会越来越重,你唯一的选择就是将项目继续维护下去,无法弃坑,直到更好的技术出现。
不知道我未来还会维护Electron多久,不过就过去几年来看,还挺开心的,应该还会继续做下去吧。
来源:知乎 www.zhihu.com
作者:
zcbenz
【知乎日报】千万用户的选择,做朋友圈里的新鲜事分享大牛。
点击下载
此问题还有
13 个回答,查看全部。
延伸阅读:
GitHub 上都有哪些值得关注学习的 iOS 开源项目?
对于一个开源 Python 量化交易平台项目的建议有哪些?