3

开始

感觉又很久很久没写东西了,心里有点忐忑不安:一直埋头工作而不去学习新知识可是程序员的大忌,刚好Deno又正式发布1.0,所以忙里偷闲也要学习一下,那么今天就是带来一波简单的Deno源码分析。

Deno vs Node.js

有人说Deno就是Destroy Node的缩写就是为了替代Node.js而生,也有人说Deno目前不成熟并不能替代现在的Node.js等等;自从Ryan指出Node.js的十大问题并且公开了新的项目Deno,在某乎上立马就展开各种(友好)讨论。不过无论怎么样,有竞争才有进步,Deno已经作为一个挑战者走进我们的视野,我们只需客观正视它的优缺点就好了。
不过个人的一些看法,Deno的出现基本意味着这是一场死斗,因为彼此基本特性实在太相似了:v8引擎,单线程异步,背靠着js的生态圈...,基本意味着开发者选择两者其一就永远不需要考虑其二,长远来看用户群可能会分裂吧;而Deno目前在这个基础上主打的是稳定性和安全性,这是服务端开发所必须的,只有满足这两个要求基础上才能去追求更高的性能,所以现在Deno的性能从官方的测试来看跟Node.js比还是有一段距离,但是个人并不太担心这一块性能差距,迟早也是会慢慢赶上来的,毕竟才1.0嘛。

前置知识

准备深入Deno部分知识还是要提前准备一下的:

  • Typescript(对于前端开发大多没啥压力)
  • Rust(主打安全和高性能的语言,学习曲线奇高,长期被编译器教做人)
  • V8引擎(Isolate,Context,Handle等等概念常记心里)

不得不说,其实rust就是Deno和Node.js分界点,感觉Deno的一个潜在目标就是把Deno的生态与rust的生态捆绑在一起,这样Deno一开始的生态比较弱的问题也可以得到一些缓解吧,另外对于前端来说迟早也是需要学习一门静态语言的,rust也是一个不错的选择(rust可是StackOverflow最受欢迎的语言)。

Deno的架构

直接贴上官网的架构图:
schematic_v0.2.png
这里官方的架构图还没来得及更新,libdeno已经替换成rusty_v8,这样意味着我们开发native插件的时候可以完全绕过了c/c++,直接使用rust就可以完成功能开发(加上rust本身自带一个可靠强大的标准库更加得心应手),当然开发者还是需要了解V8引擎相关的知识了。
再回到架构图上,我们知道Node.js是由libuv提供调度和io的能力,那么在Deno上这个角色就由rust的Tokio库提供相似的能力,而一开始Deno还是想使用go语言来提供这样的能力(Ryan果然是go语言的真粉),但是毕竟go语言也是带gc的(一个应用上同时跑两个gc,稳定性实在很难想象)而且性能上也是差rust一截,后面替换成rust也是相当明智的,另外Tokio其实对比libuv也是毫不逊色的(任务调度算法也是参考了go语言的实现)
另外在Deno里面js与rust的交互都会通过Deno.core.send和Deno.core.recv这两个方法,这样做对于应用做审计和权限控制是非常有好处,后面再会分析js和rust是如何交互的。最后例如js异步读取文件这些操作都会扔到Tokio线程池中执行,这也是Deno实现非阻塞的关键点。
然后Deno为了安全的原因,对资源都做了一层映射,原本系统的文件描述符或者其他资源都映射成了一个rid(非负整数),对资源的操作都需要通过rid进行。

|                       **Linux** | **Deno**                         |
| ------------------------------: | :------------------------------- |
|                       Processes | Web Workers                      |
|                        Syscalls | Ops                              |
|           File descriptors (fd) | [Resource ids (rid)](#resources) |
|                       Scheduler | Tokio                            |
| Userland: libc++ / glib / boost | https://deno.land/std/           |
|                 /proc/\$\$/stat | [Deno.metrics()](#metrics)       |
|                       man pages | deno types                       |

好吧,把所有的概念汇集在一起,跟Linux一对比,就会发现Deno真的很有意思了,难道是想要变成一个轻量级js应用平台吗?官方文档透露的信息实在太少了,感觉一些设计意图也没有表达出来,希望文档能够再详细一点就好了。

项目结构

.
├── cli //负责实现各种接口,包括兼容浏览器和Deno.xxx的接口
├── core //负责实例化和执行模块代码,处理js与rust之间交互还有实现event-loop
├── deno_typescript //负责编译打包typescript文件和生成v8的snapshot
├── docs //文档
├── std //std标准库
├── target
├── test_plugin
├── third_party
└── tools

自己再整理里面各个模块的依赖关系,大致如下:
截屏2020-06-06 下午9.47.23.png

当然发现更有趣的是std目录下还有有一个node的模块:

.
├── README.md
├── _fs
├── _utils.ts
├── events.ts
├── events_test.ts
├── fs.ts
├── global.ts
├── module.ts
├── module_test.ts
├── os.ts
├── os_test.ts
├── path.ts
├── process.ts
├── process_test.ts
├── querystring.ts
├── querystring_test.ts
├── tests
├── timers.ts
├── util.ts
└── util_test.ts

是不是看到这些文件名称就有一种相当熟悉的感觉,嗯,这就是deno为了兼容node模块所做的一个兼容层,虽然还没有完成,不过至少也知道deno也是有这个意愿去兼容node的模块,或许在下一个版本我们就能看到deno能够直接使用node的模块去开发应用了。

结束

暂时先介绍到这里,好像一点也没有深入到代码,真的是标题党,哈哈,下一篇文章再来深入代码分析。


tain335
576 声望196 粉丝

Keep it simple.