Node之父是谁?
没错!就是这个叫Ryan Dahl的男人在2009年创造了Node。你看,其实也不是说大神就都没头发,这位大神毛发不是挺旺盛的嘛! 不过既然是在2009年缔造的Node,那么就不得不吐槽那时候的JS了。在2009年的JavaScript啥样大家都知道(大家那时候入行了没),ES5.0(不成熟的ES5)在09年年底才刚刚发布,而ES5.1(咱们现在用的ES5)在2011年6月才开始发布并成为ISO国际标准。
想象一下即使现在有了ES6 ~ ES2020这么新的版本,JS依然经常被大家拿来吐槽,更别提那个ES5都没普及的年代了。 在那时候既没有合适的异步方式也没有模块化,也没有什么包管理啥的。那么这样的JS写大型项目或服务端项目简直就是一场灾难,于是乎就产生了各种模块化方案(Node采用了CommonJS),也有了npm、node_modules等各种历史遗留问题。 一方面是当年的Ryan Dahl技术没有现在好,思想也没有现在这么全面、另一方面当年的JS本来就很坑,用它创造出来的东西肯定不会很完美的。
但是如今的JS越来越发展壮大,虽然现在还是很坑,不过比起以前的JS来说简直强百倍。不仅有了自己的模块化,还有了Promise、Proxy、Bigint、块级作用域等一系列非常实用的特性、而且还有更好的TypeScript来为JavaScript负重前行。而Node的历史包袱实在太重,即使想支持一下标准的模块化都不得不把.js变成.mjs以保持兼容。
Deno起因
Node之父并没有一直在维护Node,他后来离开了NodeJS加入了谷歌,在谷歌他研究的主要方向就是机器学习里面的图像着色和超解像技术。虽然取得了一定的成就,但是Ryan Dahl认为现在的机器学习还很简单,离真正的人工智能还有着十万八千里。但是这并不妨碍人们去提升机器学习的技术,因为他相信,总有一天,人工智能会变得越来越完善。
提到机器学习和人工智能就不得不提python,Node他爸始终不是很喜欢Python,久而久之,就想搞一个JavaScript的人工智能开发框架(以后前端可能还得再学个人工智能)。等到他再回过头捡起Node.js,发现这个项目已经背离了他的初衷,有一些无法忽视的问题。
这些啥破玩意?那个又是些什么鬼?原来,他觉得当初自己创建Node时失误实在是太多了,他甚至还在2018年的JS开发者会上列出了自己设计NodeJS的十个错误:
- 没有坚持使用Promise
- 没有注重安全性
- 没有从GYP构建系统转到GN
- 继续使用GYP,没有提供FFI
- package.json以及依赖了npm
- 在任何地方都可以require(”somemodule“)
- package.json 提供了错误的module概念
- 设计了软件界黑洞node_modules
- require(“module”)可以不写.js
- index.js
为了弥补这些错误,他研发了一个新的项目,用来解决他的十个痛点(其实远远不止十个),这个项目就是Deno。
Deno的技术
Node的底层依赖的是C++,那Deno一样吗?
答案是否定的,一部分程序员可能还记得Deno一开始依赖的是Go语言,这曾经在GoLang社区掀起了不小的波澜。 但是好景不长,后来换成了Rust。然后好多人借机黑Go吹Rust了一番。
至于为什么换成Rust,Ryan Dahl说是因为不想同时存在两个GC(Go和TS)
Deno的名字
细心的朋友可能会发现deno这四个字母就是node的四个字母两两颠倒了一下:
- de + no = Deno
- no + de = Node
颠倒Node字母的寓意是要颠覆Node吗?
其实也差不多,它的意思是:Destroy Node (毁灭Node!)
看来Ryan Dahl对他的Deno很有信心,我是希望它能真的干掉Node的,因为它的优点实在是太过于突出啦!
那么接下来我们就来看一看Deno的优势都有哪些:
Deno的优势
内置tsc引擎,可以直接运行ts代码(还是要先编译成JS)。这就不用你每次编写完ts代码还要去手动去编译了,而且也不用再去搭建什么ts-node之类的了,方便你我他。它的内部会根据文件后缀名判断,如果是.ts后缀名,就先调用TS编译器,将其编译成 JavaScript;如果是.js后缀名,就直接传入 V8 引擎运行。
由于是用Rust语言开发的,Rust原生支持 WebAssembly,所以它也能直接运行WebAssembly。它的异步操作不使用libuv这个库,而是使用Rust的Tokio库来实现event loop。
那么为什么不像Node一样用C++而是选择用Rust呢?主要是因为Rust提供了很多现成的模块,对于Deno来说,可以节约很多开发时间。也许是看到了Rust提供了很多现成模块,Deno也决定在自己的项目中添加许多现成模块。
Deno具有安全控制,默认情况下脚本不具有读写权限。如果脚本未授权,就读写文件系统或网络,会报错。想要读写文件系统的话必须使用要参数,显式打开权限才可以。Ryan在总结Node的十个错误时曾说:V8引擎本身有很好的sandbox架构,但是有时候Node本身却没有好好利用,例如有可以直接读取Memory的例子,或者linter可以直接使用网络功能等的漏洞。从npm下载了一个包就任由他运行了,这其中存在着很大的安全隐患。
Deno 支持 Web API,尽量跟浏览器保持一致。它提供 window 这个全局对象,同时支持 fetch、webCrypto、worker 等 Web 标准,也支持 onload、onunload、addEventListener 等事件操作函数。不像Node,Web API和Node的API不一致只会增加开发者的学习成本。以后window全局对象就可以不仅仅只局限于浏览器环境啦!
Deno只支持ES模块,跟浏览器的模块加载规则一致。既没有npm,也没有npm_modules这个无底洞,同时不支持CommonJS模块,也不需要package.json文件。所有模块通过URL加载,比如import vue from “https://.vue.org”(绝对地址)或import vue from ‘./vue.runtime.js’(相对地址)。因此,Deno 不需要一个中心化的模块储存系统,可以从任何地方加载模块。但是,Deno 下载模块以后,依然会有一个总的目录,在本地缓存模块,因此可以离线使用。也就是说其实还是有一个类似于npm_modules的文件夹。
Deno 内置了开发者需要的各种功能,不再需要外部工具。打包、格式清理、测试、安装、文档生成、linting、脚本编译成可执行文件等,都有专门命令,不知道会不会在干掉Node的路上顺便把Webpack也给干掉。
Deno的劣势
虽然这么一对比,感觉NodeJS完全不是对手,但是有一点是Deno暂时望尘莫及的,那就是巨大的生态。
就像C#和Java一样,他们真的差距那么巨大吗?其实并没有吧,但是流行度差这么多有很多原因是因为生态。
就像华为想搞自己的鸿蒙系统,即使真的能比安卓优秀,但是安卓巨大的生态就足够领先很多年。当年Windows Phone系统不就是这么输的么?啥软件都没有,自然没人愿意去买Windows Phone手机。
Ryan说了,Deno现在不打算对Node做兼容处理,也就是说很多东西在Node能用但是在Deno上用不了,能不能真的干掉Node就要看广大造轮子爱好者们了,看看他们愿不愿意在Deno身上再造一个。
如果React、Vue以后都从Deno身上建生态了,那么Deno的前途就真的光明了,希望那一天能够早点到来。
重要提示
之前曾经发生过一群中国程序员以一种类似于贴吧灌水的形式在Deno项目的issue下面大量发:
- 学不动啦
- 求别更新
- 前端太难了
之类,其他issue都被淹没,导致Ryan直接关闭issue,中国程序员在世界上的形象更加一落千丈。如果学不动了可以不学,不找那种高端岗位就是了,又不是所有岗位都要求你是全栈。