为 Node.js 正名的二三事

这篇文章的起因是《程序员》杂志上的这两天在前端界闹得沸沸扬扬的文章——《2016 年前端技术观察》,我在知乎上看到相关文章的时候大概已经是凌晨两点,看完后(准确说,前端我不大了解的部分没怎么细看)「精神抖擞」,当即在知乎写下了这个回答:如何评价真阿当的文章:《2016 年前端技术观察》?

前端不够了解就不多说什么的了,但我发现现在确实还有一些不搞 Node.js 的人像上文作者那样把 Node.js 当做「玩具」来看待,所以才想写下这篇文章。

我是在大一从 PHP 和 Python 入的 Web 后端的坑,当时在学校技术组织还基本是玩票的性质,等真正在工业实践中进行 Web 后端开发,则完全是从 Node.js 开始的(老实讲,我看到的工业实践中的代码还真不一定比在学校的技术组织的代码质量高)。期间也搞过 ASP.NET Core(C#),而且目前大多数时间还是在写 PHP。我之所以要说这些是因为,总是有人会说 Node.js 只是那些前端的人才玩的,说那些人没有后端思维什么的云云。我承认前端开发与后端开发考虑的问题确实很不一样,但如果你硬要认为前端的人来搞 Node.js 不能准确的对 Node.js 在后端开发的表现进行评估,那我可是一开始就真真切切的从一个后端的角度来看待 Node.js 的。

第一个需要为 Node.js 正名的是:Node.js 在目前主要还是后端的技术(至少肯定不是前端的技术)。尽管前端的同学常拿 NPM 来做包管理、用 Node.js 来写一些自动化脚本,也改变不了 Node.js 是为 Web 后端设计的本质。当然,现在 Node.js 跟很多主要用来做 Web 后端的语言一样,也可以来写 PC 端应用,但还不是主流。岗位划分上,很多公司把 Node.js 归类到前端组,这在一定程度上误导了初学者。

从我在 PHP、Python、ASP.NET Core(C#)、Node.js 这些 Web 后端的体验来看,我非但没有觉得 Node.js 在后端开发上有什么明显的不足,反而觉得在很多方面比那些传统主流的 Web 后端技术要好上不少。下面来一一分析。

不稳定?

这大概是我最常听到的对 Node.js 的质疑。当跟不熟悉 Node.js 的开发者讨论的时候,他们总是会质疑用 Node.js 写的应用是不是不稳定?能不能写大型应用?有哪些业界有名的公司在使用它?……然而如果问他们为什么说 Node.js 不够稳定时,他们开始变得支支吾吾,说自己不是主要搞 Node.js 的对此并不了解,只是听别人常这么说。

我不知道质疑 Node.js 是否稳定的疑虑是从哪里跑出来的(早期不成熟版本给人的印象?我不知道……),从我个人的开发经验来看,那些写过 Node.js(以下或简称为 Node) 还质疑其稳定性的人往往是因为自己对 Node 的理解不够深。比如经典的异步流程控制问题,在具体写代码时确实需要注意一些细节,但关键还是要理解 Node 异步的本质,这样才能轻松写出符合自己对它的行为期望的代码。但不能因为自己对语言最大的特点理解不够,写出了自己难以解释其行为的代码,就对别人说这门语言(或者说实现)不稳定吧。

如果你还是对 Node 的稳定性有疑虑,你知道 PM2 吧?那 Forever 呢?如果你依然不放心,那你还可以在 Node 应用外加一层反向代理,过滤掉网络世界里一些「肮脏」的信息。

性能不够?

Node 当初就是以单线程异步非阻塞特性在高并发下的优良表现进入大家的视野的,加上 Google 的 V8 JavaScript 引擎,在性能上至少绝对不会成为其短板。虽然微软新推出的 ASP.NET Core 一度宣称其性能是 Node.js 的 8 倍,但脱离的具体的业务场景来谈性能完全就是耍流氓,这种测试与其说是技术上性能的对比,不如说是为了 marketing 的目的而制造的噱头。

进一步说,真实的业务场景中语言(或者说其实现和技术栈,以下同)几乎不可能真正成为性能瓶颈,带来的瓶颈的往往是 I/O 部分。注意,这并不说语言对此没有责任,难以优化的 I/O 性能瓶颈可能是因为开发人员由于语言特性写出了不易扩展和优化的代码,这往往是对性能产生更大影响也更有意义的方面,所以因此换语言也是有可能的(比如 Twitter 曾经从 Rails 换到 Scala),但不是说语言本身的运行性能有什么太大的问题。

第三方库的质量太差?

我认为这非但不是 Node 技术生态圈的缺点,反而是其对比其他技术生态圈最大的优势。无非你遇到什么问题,无论你想找什么样的解决方案,在 2016 年接近尾声的今天,你都可以在社区找到灵感、吸收别人的养分、站在巨人的肩膀上。换句话说,你在社区提出一个问题,你可以快速且明显地感受到社区的热情。

截至目前,NPM 上已经有 385684 个 packages。而 GitHub 上 2016 年流行语言排名,JavaScript 更是超过第二名两倍还不止(当然这之中前端 JS 的贡献也很大):

15 most popular languages used on GitHub in 2016

可以说,目前没有一个技术社区的社区活跃度比得上 Node/JS 社区。

而至于质疑第三方包质量太差缺乏审核……诶,你是知道广电的电影审查制度的吧?

正是因为 NPM 使得发布一个包变得如此的简单,才极大的激发了开发者的热情。积木总是越搭才会越高的,需求也总是多种多样的,正是庞大的第三方包的基数使得开发者们有了更多的选择,优秀的第三方包也会在绝对数量上越来越多,从而可以实现更复杂更困难的业务需求。

其他问题……

自动化文档?参数验证?

Swagger 不是针对某一门特定语言的(ASP.NET Core 的官方文档就是推荐的 Swagger 作为文档系统),也可以参考我的这篇文章:使用 Swagger 构建 Express API Server 的文档系统

Express 不够强大?不够标准?

Express 可以很好的让初学者了解一个常规的 Web 框架在底层是怎么处理问题的,甚至还可以阅读其源码了解其实现。但如果你还是因为不管什么原因不喜欢它,你还可以有各种各样的选择:Hand-picked registry of Node.js frameworks。这里我想着重提一下 FeathersJS,如果你觉得 Express 对于 HTTP(S) 或者 REST 标准的支持不够专一和规范,你可以考虑看看这个框架,个人认为它在很多关键问题的处理上都有很规范的做法(拿 Express 跟它比可能对 Express 不大公平,它本身是基于 Express 的更高层次上的封装)。

自动化测试?

不必多说什么,mocha/should(chai)/supertest/istanbul 基本已经成为共识,大不了再加个 rewire。而如果这样你还觉得麻烦,社区里已经有各种各样基于这些包的使用更方便的封装了,基本思路大概是像写配置一样写测试样例,然后写 Parser 把这些测例加载并解析再去自动化测试。

……

总结

其实上述我说的这些问题早就有技术前辈们的布道和背书,我也不过是拾拾牙慧而已。技术人还是要多保持独立思考,与其道听途说,不如实实在在的自己去了解实践,亲身去感受,得出自己的结论。

哦,对了,我这篇文章也可能完全都是错的

:D