[技术产品] 用node-webkit做桌面应用
小长假就这么结束了,本来打算抽空用node-webkit写点什么的,结果中间一天加班,前后两天出去玩,累了个半死。也没顾上。
node-webkit是两周前我才刚刚认识的桌面开发利器。那天程序君写了篇关于github atom的文章,中间有段文字做了大胆的猜测:「这就是Atom最大的亮点!web native。在此之下,less style,coffeescript plugin,nodejs integration都水到渠成。看上去atom的源代码来自chrome —— 我觉得atom很可能是一款以某种方式运行本地web app的浏览器。chrome的源代码base在webkit上(貌似是bsd),所以atom可以任意修改。很可能chrome上面的沙箱环境(不允许web app访问本地资源,如文件系统)被移除,然后nodejs以某种方式被集成进来(这样javascript可以访问文件系统等本地资源)。」
很快有不少朋友或在知乎上,或在微信里给我留言,不约而同地提到了一个技术:node-webkit。所谓「三人行,必有我师」,感谢这些读者,你们为我开了一扇窗。^_^ 孤陋寡闻的程序君知道了这个技术后,便如饥似渴地研究了下去...如今两周过去了,程序君也有点点小小的心得来回馈大家,尤其是当时为我指引迷津的朋友。
我会按照:what - why - how 的顺序介绍node-webkit。
What
不了解web-native技术的程序员可以先稍稍了解一下webkit和基于webkit之上的chromium两个开源项目。两者都是BSD license的浏览器项目。chromium的商业化产品就是我们熟悉的chrome浏览器(我的好基友)。chromium基本就是一个操作系统,里面提供了非常复杂的协议栈和各种功能,包括但不限于:
- 跨平台的系统资源访问,如文件系统
- 各种互联网相关协议,如HTTP, HTTPS, FTP, DNS, etc.
- 强大的并发处理能力
- 各种压缩协议和算法
- 页面快速渲染
- javascript执行引擎
- 磁盘缓存机制
- ...
可以看这张图:
然而,为了避免来自非受信域(互联网)上的应用进行一些非法操作,chromium提供了严格的沙箱环境,让本地的很多信息(比如文件系统)不会暴露给互联网上的应用。
chronium强大的功能让人垂涎,又是BSD license,以此为基础做一个应用程序诱惑力很大:跨平台,各种已经建好的功能,深度整合互联网技术等。所以它是做桌面应用的一个利器。可是,chronium对于未在浏览器行业浸淫的小团队来说困难了些。因为你要读懂chronium的content API文档,要了解很多技术细节,更重要的是,基本上你需要使用C++来开发应用。google看到了里面的机会,将chronium项目封装出一套使用简单的API,并(在第三方的协助下)提供了很多不同语言的binding,这样你就可以使用你熟悉的语言进行桌面应用程序的开发,这个就是CEF(Chrome Embedded Framework)。
投抱CEF怀抱的知名项目有:
- Adobe Bracket
- Evernote
- 豌豆荚
我没有太研究CEF,所以就不多说。
node-webkit另辟蹊跷,它没有基于官方的CEF进行二次开发,而是做了如下事情:
(1) 将nodejs的消息循环和chromium的结合起来,让使用者可以在dom里调用nodej.js的函数。
(2) 合并nodejs和chromium两者里的web引擎(都基于v8)。这样所有javascript运行在一个context下。
(3) 修改沙箱模型,去除很多对桌面应用而言没有意义的安全手段,让应用可以最大程度访问本地资源(比如文件,本地网络等)。
node-webkit最大优势是很巧妙地把nodejs结合到chronium里,让你可以使用几乎所有的nodejs社区里的module。
投抱node-webkit的知名项目有 LightTable。
Why
无论CEF还是node-webkit,都大大降低了写复杂桌面应用的难度:不需要C++,不需要QT,不需要java,你只需要懂html,css和javascript,就能写出本来难度不小的桌面应用。 除此之外,还有好几个跟现代软件相关的原因:
现代软件不和互联网结合就是慢性自杀。
现代软件没有漂亮的UI就如同没有学会打扮但很有内涵的姑娘。
现代软件不能跨平台就会少很多高端用户(mac占有率已经接近7%了)。
所有种种,CEF和node-webkit都能提供支持,相对于CEF,node-webkit使用起来更简单,对nodejs社区的良好支持是个杀手锏。如果你稍稍看看adobe brackets(一个代码编辑器)的代码,就会发现其在本地文件系统的支持上花了多少功夫。而使用node-webkit,引用fs的package即可。(当然,我相信不久的将来,CEF对此会做修改和优化)
How
"How" 是我们开启一段程序旅程的最困难的部分。所谓细节是魔鬼,难就难在怎么做这样的细节上。对于node-webkit,你可以follow其repo(https://github.com/rogerwang/node-webkit)里的wiki,一步一步做,就能成功做出一个Hello world程序。
这似乎很简单 - 不就是写个 package.json,外加个index.html?何难之有?
但我们想要的绝对不是hello world。我们想做的往往要复杂得多。所以我们需要一套完整的解决方案,问问自己这些问题:
(1) 我的代码用什么撰写?(程序君用coffeescript, less和handlebars)
(2) 我的应用打算使用什么样的MVC库?(ember, angular, backbone, etc.)
(3) 我的应用都有那些前端的(bower)和后端的依赖(npm)?
(4) 如何打包和发行?
(5) 如何测试?
(6) ...
怎么撰写代码取决于你打算如何维护你的应用。最简单的方式当然是直接撰写html, css, js,但是这样容易产生意大利面条式的代码。一般web前端都是使用各种技术最终打包出来html, css和js。
如何测试很重要。虽然你在写桌面应用,但大部分代码都是为界面和交互提供服务的。如果这样的代码还不得不运行在node-webkit里,而不是浏览器中,那么开发的效率会大打折扣。
经过深入探索,程序君获得的答案是这些工具和项目:
brunch是打包工具,后两者都是项目的template。
angular的拥趸直接用node-webkit-hipster-seed就好了,封装得已经近乎完美。但angular不是程序君的菜,所以程序君又重新拾起已一年多未使用的ember,基于 tapas-with-ember 做了一套符合程序君自己需要的template project。你如果感兴趣,可以
$ brunch new https://github.com/coderena/node-webkit-template test
来试试这个template结构。基本上它提供了一个非常灵活的架构,可以适应应用程序的不断增长。
先写这么多,等我有了更多的经验,会继续分享。
如果你对本文感兴趣,欢迎订阅公众号『程序人生』(搜索微信号 programmer_life)。每天一篇原汁原味的文章,早8点与您相会。