当前位置: 首页 > 科技观察

Deno不是下一代Node.js

时间:2023-03-12 06:08:29 科技观察

这几天前端圈最火的事件莫过于ry(RyanDahl)的新项目deno。许多IT新闻和媒体都使用了标题:“下一代Node.js”。这个周末看了deno的源码,特地写了这篇文章。超长文字警告(5000字,11张图片)。0.为什么要开发Deno?这是我上周制作的图表,它提供了JavaScript发展的简要历史。我只是对其进行了一些修改,并添加了有关Node.js和Deno发布时间的注释。Node.js和Deno是RyanDahl分别在2009年和2018年开发的非浏览器JavaScript运行时,基于当年最新的前端技术。RyanDahl开发deno不是因为“只是为了好玩”,也不是为了取代node。下面慢慢解释。1.目前deno只是一个demo。这两天花时间阅读了deno的源码(幸好是初级阶段,源码很少,很容易看懂),也阅读了所有的issues和PR。不知道怎么“从官方介绍来看,可以算是下一代的Node”。既然是Node.js之父的新作,自然离不开Node.js的讨论。并且作者很皮包骨头的回复:主要区别是Node能用,Deno不能用:)***的区别是:Node能用,Deno不行:)目前Deno只是一个Demo,连二进制版本都没有version是No。幸运的是从源码编译比较简单(如果你不是windows系统的话)。在高层,Deno提供了尽可能简单的V8与系统API的绑定。为什么要用Golang而不是C++,因为Golang比Node.至于为什么不选择Rust,作者没有回答。我们来比较一下两者的启动性能。单独运行:console.log('Helloworld')之前写过一篇文章:Node.js新计划:使用V8快照启动速度提升8倍,那么如果我们使用--without-snapshot参数编译Node呢.js?还是有很大区别的,毕竟deno需要加载TypeScript编译器。毕竟是试玩版,希望以后能优化一下。另一个性能提升的思路是,可以使用LLVM作为后端编译器,将TypeScript代码编译成WebAssembly,然后在V8中运行,甚至可以直接将源代码编译成二进制代码运行。RyanDahl说deno只需要一个编译器,就是TS。不过既然deno是兼容浏览器的,那么WebAssembly应该也是支持的。Deno可以缓存ts的编译结果(~/.deno/cache),所以目前关注的重点是启动速度和初始编译速度。要么是先编译再发布,这样deno就背离了开发的初衷。Deno是一个ts运行时,所以你应该能够直接运行ts代码。如果提前把ts编译成js,那么deno会回退到js运行时。2.初学者应该学Node.js还是Deno?RyanDahl对这个问题有一个简洁的答案:使用Node。Deno是一个原型/实验。使用节点。Deno只是一个原型或实验产品。从介绍中可以看出,Deno的目标不是兼容Node,而是兼容浏览器。因此,Deno无意取代Node.js,也无意成为Node.js的下一代,更无意抛弃npm重建Node生态。Deno目前正在拥抱浏览器生态。不得不说,这个进球真的很棒。RyanDahl开发了Node.js,社区构建了整个npm生态系统。我在另一个回答justjavac:纯前端开发眼中的nodejs到底是什么?它说“Node.js是前端工程的重要支柱之一”。虽然后来RyanDahl离开了Node.js去了Golang社区,但是现在RyanDahl又回来了,把Golang带到JavaScript社区,开发Deno,拥抱浏览器生态。👍我们来看看deno关于WebAPI的目标:高层Console√File/FileList/FileReader/BlobXMLHttpRequestWebSocket中层AudioContext/AudioBufferCanvas甚至包括对webGL和GPU的支持。3.Deno的架构ParsaGhadimi画了一张Deno的架构图:底层使用作者开发的v8worker2,event-loop基于pub/sub模型。对于v8worker,可以看看这个PPT:https://docs.google.com/prese...我很好奇的是,deno使用的是protobuf,而不是Mojo。既然目标是兼容浏览器,而不是使用Mojo,而是在protobuf上重新造轮子,可见RyanDahl才是真正的“轮子哥”。不过从issue可以看出,RyanDahl之前并没有听说过Mojo,但是看了mojo之后,还是觉得protobuf的选择是正确的。Mojo是Google开发的新一代IPC机制,用于替代旧的ChromeIPC。目前Chrome的最新版本是67,谷歌的计划是在2019年的75版本中将所有旧的IPC全部换成mojo。Mojo的思路确实和protobuf类似,毕竟是谷歌的。旧的IPC系统是基于2个进程(线程)之间的命名管道(IPC::Channel)实现的。这个管道是一个队列,进程之间的IPC消息是按照先进先出的顺序依次传递的,所以不同的IPC消息之间存在顺序依赖。相比之下,Mojo为每个接口创建了独立的消息管道,保证了不同接口的IPC是独立的。并且为接口创建一个独立的消息管道成本并不昂贵,只需要分配少量的堆内存。Mojo的架构设计:我们可以看看Chrome引入Mojo后的架构变化。之前:之后:是不是有点微服务的感觉。熟悉Java的Spring的人可以清楚地看到这种依赖倒置。Blink最初是浏览器顶层的排版引擎。通过Mojo,Blink成为了一个中间模块。最近流行的Flutter也是基于Mojo架构的。4.TypeScriptVSJavaScript简介deno是一个安全的TypeScript运行时环境。但是当我们查看源码时,会发现deno被集成到了一个TypeScript编译器中,在ry/deno的入口文件中:main.go//It'suptolibraryuserstocall//deno.Eval("deno_main.js","denoMain()")funcEval(filenamestring,codestring){err:=worker.Load(filename,code)exitOnError(err)}//是suptolibraryuserstocall//deno.Eval("deno_main.js","denoMain()")funcEval(filenamestring,codestring){err:=worker.Load(filename,code)exitOnError(err)}使用V8运行的deno_main.js文件。它是JavaScript,而不是TypeScript。在前面的分析中,我们知道这会影响deno的初始启动速度。那么执行速度呢?理论上,TypeScript是一种静态类型语言,编译后的JavaScript代码会执行得更快。我之前在《前端程序员应该懂点V8 知识》里提到过,V8有一个类型反馈来提升JavaScript的性能。V8在执行函数时,会根据函数传入的实参进行即时编译(JIT)(注意是实参,不是形参,因为JavaScript形参是没有类型的):该类型调用一个函数,V8将执行一个反优化(Deopt)操作。(去掉之前优化过的结果称为“反优化”)但是如果我们使用TypeScript,所有的参数都是按类型标记的,所以可以防止V8引擎在内部进行反优化操作。5、对deno性能的展望和猜想虽然TypeScript可以避免V8引擎的反优化操作,但是V8执行的是ts编译的结果。通过字节码或者机器码我们可以看出,V8还是会生成TypeCheckCode,在每次调用函数之前,V8都会检查实参的类型。也就是说,虽然TypeScript保证了函数的参数类型,但是编译成JavaScript后,V8无法确定函数的参数类型,只能通过每次调用前的检查来保证参数类型。其次,V8在遇到函数定义时,并不知道参数的类型,只有在函数被调用后,V8才能判断函数的类型,并对函数进行TypedJIT编译。这里还有一个矛盾。typescript在定义函数的时候就已经知道了形参的类型,而V8只是在函数调用的时候根据实参的类型进行了优化。因此,目前的deno架构还存在很多问题,毕竟只是一个demo。未来还有很多方向可以优化。V8是一个JavaScript运行时,如果将deno定义为“安全的TypeScript运行时”,至少在目前的架构上,性能上会有很大的损失。但是目前还没有TypeScript运行时,退而求其次的是在V8前面放一个TypeScript编译器。执行过程是这样的:虽然我从来没有在项目中使用过TypeScript,但是基本上我在项目中写的第三方库都会提供一个d.ts文件。目前,TypeScript***的使用还体现在开发和维护过程中。我们想到的一种方式是fork一个V8的源码,然后把编译过程集成进去。TypeScript在编译成JavaScript的过程中也需要一个AST,然后生成js代码。V8在执行js代码时,会解析另一个AST,并根据AST生成中间代码(ByteCode)。如果TypeScript可以直接生成相应的字节码,将会提高运行时性能。不过,RyanDahl可能不会那样做。但不一定,毕竟社区已经将TypeScript的一个子集编译成了WebAssembly。此前,微软的JScript和VBScript在与JavaScript的竞争中落败,但现在TypeScript势头正猛。虽然与ES规范的兼容阻碍了TypeScript的发展,但希望微软能够提供TS运行时,或者在Chakra引擎中增加对TS运行时的支持。6.结论不管怎样,deno是一个非常伟大的项目,但它不是“下一代Node.js”。PS:RyanDahl昨天在JSConf上发表了演讲《Design Mistakes in Node》。目前只有PPT,没有Youtube视频。而在8年前的2009年,RyanDahl也在JSConf上发表了演讲,Node.js由此诞生。PPT:http://tinyclouds.org/jsconf.pdfYouTube:RyanDahl介绍Node.js