在稍早前的 JS Conf Berlin 上,被称为 Nodejs 之父的 Ryan Dahl 发表了《10 Things I Regret About Node.js》演讲,并且发布了新项目 Deno,值得一提的是,这是 Ry 的第二次公开演讲,而第一次是发布 Node.js,本文将带领大家回顾一下 Ry 演讲上所提到的重点。
演讲第一部分: Nodejs 的成功
这一部分,讲了 Node 的发展历程,Ry 认为 Node 在 I/0,事件驱动的 http server 方面已经做得很好了,提到了 Node 对一些协议的支持,跨平台,以及 npm 生态系统等促成 Node 成功的因素,以及感谢了一些为 Node 做出过贡献的人。 Ry 始终认为 JavaScript 是最好的动态语言,而动态语言用来做科学计算是合适不过了(这可能和 Ry 离开 Node 后加入 Google 的 Brain 团队,从事深度学习方面的研究的历程有关)。
演讲第二部分: 对 Nodejs 的吐槽
这一部分可以说是整个演讲的高潮,前后吐槽了 Node 上 7(不是应该 10 个么???) 个让 RY 觉得遗憾的设计。
1. 没有坚持使用 Promise
Promise 是 async/await 的必要抽象,Promise 的没有坚持使用导致后面 Node 的很多异步 API 严重老化。
2. 没有足够的安全性
V8 本身是一个非常好的沙箱环境,但是 Node 在早期的设计中却没有利用好这一先天优势,导致程序可以轻松访问系统和网络。
3. 错误地坚持使用 GYP
由于 Chrome 放弃了 GYP,使得 Node 是 GYP 唯一的用户,并且 Ry 认为这其中有太多的复杂且不必要的抽象,与其让用户自己去编写 C++ 扩展来绑定 V8,不如提供一个核心外部函数接口来得更加可靠。Ry 认为在构建系统上的设计错误是 Node 的最大遗憾。
4. package.json
package.json 因为 require 的支持,使得这后来成了事实上的模块标准,可是很遗憾,因为默许了 package.json 的存在,可是 require(‘module') 又是不明确的,导致当出现本地依赖库或者私有依赖库时候,变得很混乱。并且 package.json 包含了太多冗余描述,许可证,仓库,描述等等,而且 package.json 提出的“module”作为文件目录也不是必要的抽象。
5. node_module
增加了模块的解析复杂度,并且是偏离了浏览器语义,但是现在已经没法剔除出去了。
6. require('module') 没有加上扩展名".js”
多此一举的做法,模块加载器必须得去猜测是‘.js’还是’.json’,并且也是跟浏览器语义不符的。
7. index.js
实际上默认去加载 index.js 也是没有必要的,因为可能会有 index.html….
以上提到的遗憾都主要集中在代码管理上而非早期 Ry 关注的建立高性能服务器上。实际上在 Ry 提出这些遗憾的时候,相当于已经提出了新一代 js/ts 的 v8 runtime 的原型 -> Deno,而其主要目标就是解决以上问题。
演讲第三部分: 对 Deno 的介绍和期望
1.安全性
Deno 将利用 JS 是安全沙箱的事实,允许安全运行不受信任的程序
- 默认情况下,不允许程序直接访问网路或者文件系统
- 可以通过 —allow-net —allow-write 的方式访问 不允许扩展函数直接绑定到 V8 上,简化流程,也易于审计
- 所有系统调用都通过消息传递完成(protobuf 序列化)
- 两个原生函数: send 和 recv
2.简化模块系统
- 不会去尝试和现有 Node 模块系统兼容
- 仅导入相对/绝对的 URL,并且导入路径必须提供扩展名
- 远程 URL 在第一次加载之后将被永远缓存,只有提供 --reload 才能再次获取资源,可以通过指定非默认缓存目录来绕过
3.将 TypeScript 编译器内置于可执行文件之中
- Deno 内置 TS 编译器以实现模块解析与构建结果的增量缓存
- 未修改的 TS 文件不会被重新编译
- 普通 JS 也同样有效
- 利用 V8 的 snapshot 来快速启动,暂未在原型中设计 (参考《使用 v8 snapshot 将启动速度提升 8 倍》)
4.单个可执行文件
5.充分利用 2018 技术优势
使用 Parcel 把 Node 模块编译打包,来实现运行时的自举。
以原生代码的方式提供强大的基础设施
- 已有其他机制负责实现 HTTP,而此前的 Node 是无法实现的
- 目前 Deno 的非 JS 部分以 go 语言编写,但还没全面完成原型设计,其实 Rust 和 C++ 在某些方面也不错
6.其它
- 发生未捕获 Promise 错误时直接终止程序
- 支持 top-level 的 await
- 兼容浏览器(当功能重叠时)
Ry 的演讲大致就是以上这些内容,尽管 Deno 目前还是不可用的,也没有发行二进制版本,但是该项目推出短短数日便获得了上万个 Star。
后话:
目前大前端开发的工程化,SSR 等能力基本都由 Node 提供,加上一些利用 Node 优势而搭建的后端服务,都有一定发展时间,因此对于 JS 开发者而言 Node 在未来很长一段时间内依然是值得继续学习的一个项目。
当然如果 Deno 有部分设计你是认可的,那现在最好的方法就是开始投资学习,从学习 Go 语言开始,学完 Go 就去看 Deno 源码,边看还可以边提 PR,看完 Deno 源码后 API 也差不多出来了,你就可以用 TypeScript 写 Demo 了,最后即使 Deno 没人用进了博物馆,你还学会了 Go 和 Typescript,还为大型开源项目贡献过源码....
参考资料: