【第1312期】Node.js开发之父:十个Node.js的设计错误以及其终极解决办法
前言
今日早读文章由@David Ng、@Starkwang分享。
正文从这开始~
养不教,父之过。Node.js 创始人 @Ryan Dahl 在 JSconf 2018点评了十个在设计和更新Node.js时犯下的错误。
2008年Chrome才刚刚出现,现在已经更新到了版本66.0了。而Node.js其实也是近十年冒起的代表。它只是2009年的产物,现在出到版本10,却在软件界家喻户晓。
不过有用过Node.js作为production 的工程师,应该很同意Node.js其中一个重要的特征就是:内存泄漏。所以在实际开发时,往往都要用forever来自动定时重启Node.js Server。
很多底层的设计错误
要了解这些错误以其重要性,可能要对程序设计语言和软件工程有深入点的认识。Ryan Dahl在Node.js中的设计和应用,直接或间接影响了不少重要的软件,甚至整个软件行业。因为有不少软件和平台都以Node为根基。
Ryan Dahl在演讲中用了个很严重的说法指出:
动态语言适合与一次性的科学演算,而Javascript就是最好的例子。
不然,Node中充满着投诉的缺陷。
真的是相当严重的懊悔。因此,他以Design mistakes in Node为题,指出了十个悔不当初的错误。
后悔之一:没有坚持使用Promise
在2009年6月,Node中开始引入Javascript的Promise,但在2010年2月就移除掉了。
结果,随着日子久远,Node里面就遍布着async/await 和 promise的不同 异步API的设计,直至现在都极难整合。
后悔之二:看轻了安全性
JavaScript Engine V8 本身有很好的sandbox架构,但是有时候Node.js本身没有好好利用,例如有可以直接读取Memory的例子,或者 linter 可以直接使用网络功能等的漏洞。
后悔之三:没有从GYP构建系统转到GN
Node.js用到的Javascript Engine V8 一开始是使用GYP构建的,Node理所当然也跟随,后来V8转用了GN(Generate Ninja),只剩下Node成为唯一的用户。GN比用Python写的GYP快接近20倍,对于使用者来说,简直就是天澜之别。
Ryan更这样说:
继续适用GYP该是Node核心的最大失误。
后悔之四:继续使用GYP,没有提供FFI
继续用GYP引申到另一个难题,就是怎么样去提供跨程序语言的接口。
现在Node只提供了由C++到V8的binding指南,事实上对开发者来说是严重不足的,很多人建议过转用Foreign Function Interface (FFI)的模式,但都一一被当时的Ryan忽略了。
后悔之五:package.json以及依赖了npm
npm的Issac发明了package.json,Ryan认为把Node能在main program中用require()读取npm的package.json 是一个坏的开始。
后来,演化至Node中包含npm作为标准,以至现在Node的Module变成了由npm集权了。
事实上,因为npm而引起的灾难性事件也不少,其中最有名的应该算2016年发生的left-pad chaos。
后悔之六:在任何地方也可以require(“somemodule”)
你可以不必在package.json中注明dependency,在Node中几乎是任何地方也能够require local 或者是 remote的程序代码。
后悔之七:package.json 提供了错误的module 概念
你以为放在同一个文件夹里的就是一个module了,少年你还是太年轻了。其实并没有这样的一个机制。
其实现在package.json 并没有公认标准,里面可以包含很多毫无关系的信息,比如名称、版本、License、详细说明等,以致package.json 整个文件像是杂物间一样。
例如我们用URL导入项目的话,URL里就以包含了所需的版本信息,而不应再写在package.json里。
后悔之八:设计了软件界黑洞node_modules
有试过npm之后,要等很久,然后发现项目下载了几百MB的node_module吗?
这是因为Node里Vendored-by-default机制有点好心办坏事。从而令node_module主动地安装了所有module的dependencies。这个设计另要处理node_module的方式变得超复杂,也变成Node里面最令人苦恼的一个地方。
Ryan 对这个设计应该是彻底地后悔。
這是我的錯-十分抱歉。不幸的是,現在已經無法砍掉了。
后悔之九:require(“module”)没有逼人用文件扩展名.js
不知道为什么要这样的简洁。
在浏览器中<script> 标签是不能省略.js部分的,这令Node要多用几次不必要的查询,才能猜到工程师想要引入什么文件。
后悔之十:index.js
由于index.html 的传统,很合理有inde.js吧?但其实有了package.json后,index.js就变得不必要了。
结论
Node.js现在遇到的问题,其实大多上都是软件管理上的问题,例如API、FFI,引入文件的方案和dependency管理上的痛苦。
结果呢,Ryan针对以上的反思,提出了一个方案,就是开发以安全性、程序代码简洁性,符合2018年标准为原则的框架 - deno。
deno是以Golang + yarn + TS 为主要的技术栈,舍弃了Node.js 本来C++ 和Javascript。deno暂时还是在初步阶段,要试玩的话,还是要由
source code 自行编译。
不过,Ryan 看来相当满意deno暂时的设计,起码应该不会犯和Node 相同的错误了。
其实,deno并不是想要直接取代Node.js的,而是提出了一个新的框架去协助工程师去构建未来更加合理的软件。
关于deno,在2018-06-13,Ryan 发布了 deno 的第二版原型,主要的变化有:
使用 GN 这个构建工具,这是 chromium 团队使用的构建工具
使用 V8 Snapshots 提升启动速度(之前其实就提到过了)
移除 Golang,因为不想同时存在两个 GC(Go和TS)
弄了一个 C++ 库叫 libdeno,负责 TS 的运行时环境
ry 还提到未来可能会考虑把目前的 C++ 改写成 Rust
PPT:http://tinyclouds.org/jsconf.pdf
视频:https://www.youtube.com/watch?v=M3BM9TB-8yA
关于本文
作者:@David Ng、@Starkwang
原文:
https://m.oursky.com/node-js-開發之父-十個node-js-的設計錯誤-以及其終極解決辦法-f0db0afb496e
https://zhuanlan.zhihu.com/p/38071588