IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    维护一个大型开源项目是怎样的体验?

    zcbenz发表于 2016-05-25 13:30:00
    love 0
    这次籍着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的绑定,也就是:
    require('nw.gui')
    

    如果你有使用过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 量化交易平台项目的建议有哪些?


沪ICP备19023445号-2号
友情链接