Deno 兼容浏览器具体指的是什么?

Deno 里面有一句描述:"Aims to be browser compatible",能够看到 Deno 的目标是兼容浏览器。那么这里的兼容浏览器到底如何是什么意思呢?html

我简单谈谈个人理解吧。前端

首先这里的兼容性确定不是 Deno 直接在浏览器端运行。由于 Deno 是一个和浏览器平级的 Runtime。node

不少人还有误解觉得兼容浏览器指的是 Deno 会提供“相似 Node.js 里的 UMD 写法”。首先咱们明确一点,这里的兼容不是单指语法层面的兼容,并非说要兼容 ES3 ES5。因此不要产生这种误解,觉得能够经过 babel 兼容 Node.js 和 Deno。git

在 Deno 的 Roadmap 里面做者就已经写到了:github

Deno does not aim to be API compatible with Node in any respect. Deno will export a single flat namespace "deno" under which all core functions are defined. We leave it up to users to wrap Deno's namespace to provide some compatibility with Node.

这里的兼容,个人理解是兼容浏览器的 API 和生态。(坐等被打脸)编程

以前有个 issue discussion: struct the browser-compatible APIs #82 讨论这个问题,在 issue 中列举了一些想要兼容的浏览器 API:api

  • High level浏览器

    • Console ✓
    • URL ✓
    • File/FileList/FileReader/Blob
    • XMLHttpRequest/Fetch
    • WebSocket
    • URLSearchParams
  • Middle level安全

    • AudioContext/AudioBuffer
    • Canvas

讨论中还包括 WebGL 设置 GPU 的支持。咱们能够隐约猜到 Deno 的一个目标就是让浏览器中的代码能够直接运行在 Deno 上面服务器

个人观点依然是:Deno 不是下一代 Node.js。(再次坐等被打脸)

Deno 是一个“A secure TypeScript runtime on V8”。一个安全的基于 V8 的 TypeScript 运行时,这个怎么理解呢。

浏览器能够认为是安全的 JavaScript 运行时,全部的 JavaScript 代码都是在沙盒(Sandbox)里面运行。浏览器虽然安装在你的电脑上,可是浏览器里面运行的 JavaScript 代码能够来自世界各地,换言之浏览器里面运行的都是不受信代码,如何保证浏览器的 JavaScript 代码不破坏你的电脑系统,这是浏览器安全机制须要解决的一个问题。而 Node.js 则不是,和任何的 Web 服务器同样,Node.js 运行的是受信代码

以前 V8 出现了关于逃逸分析(Escape Analysis)的安全漏洞,Chrome 采起了紧急措施,在下一个版本中删掉了逃逸分析相关的功能,相比之下,Node.js 则没有受到影响,由于 Node.js 运行的代码原本就是受信的。

从这个角度讲,Deno 和浏览器的定位很像。

由于咱们能够看到,兼容服务器端生态和兼容浏览器端生态的一个区别:

  • 浏览器里面运行的都是不受信代码
  • 服务器运行的是受信代码

咱们再换一个角度聊聊服务器生态。

不少人还有一个误解,就是以为上面提到的那些 API,对于 Node.js 也彻底能够兼容,好比 Console、URL、XMLHttpRequest/Fetch 等,不少 API 都已经被 Node.js 实现了。

当 Node.js 被开发出来的时候,相似 File、URL、Buffer 这类的 API 浏览器端都尚未,但因为 Node.js 定位为服务器端运行平台,所以 Node.js 参考的是其余 Web 服务器或者服务器编程语言。例如文件系统(File System),实现了一系列 POSIX(Portable Operating System Interface,可移植操做系统接口) 兼容的函数和功能。

还有一点须要注意的是 Node.js 和浏览器的趋同化,例如 Node.js 7 加入的 URL API,而当今的主流浏览器也都提供了这个 API,这是由于 Node.js 也使用了 WHATWG URL 标准。

WHATWG 的全称是 Web Hypertext Application Technology Working Group,网页超文本应用技术工做小组。这是一个至关“有重量”的组织,当 W3C 决定放弃 HTML 打算将将来的重点放在 XHTML 2.0 上时,WHATWG 坚定拥护 HTML,并制定了下一代 HTML 计划。最终 WHATWG 说服了 W3C 并与其一块儿发布了 HTML5。

现在 Web 的飞速发展咱们要感谢这些组织的努力。

那么如今就有一个疑问了:若是 Node.js、浏览器、Deno 都使用这些标准后,那么他们是否是就会变得同样,Deno 会不会取代 Node.js,成为下一代 Node.js?或者 Deno 变成一个和 Node.js 同样可是比 Node.js 还难用的平台,最终被边缘化或者被抛弃?

不会。由于性能和安全是不可兼得的,好比 File/FileReader/Blob 这种 API 天生就是为浏览器端沙盒环境设计的(WHATWG 好多标准都是为浏览器设计的)。Node.js 尚未提供相应的 API,并且也不打算提供,毕竟在服务器端环境咱们更须要的是文件系统,因此 Node.js 不去拥抱 WHATWG,而选择了 POSIX。

既然谈到了这个,那我就再讲的深刻一点吧,深刻到底层看看为何 Node.js 不是用 Blob 和 FileReader 来读取文件。

在浏览器端文件一般来自于网络,由 url 提供,或者来自于表单的用户主动选择。不管何种方式都是由浏览器来完成文件的读取,并把文件内容加载到内存缓冲区中,这时 JavaScript 能够经过 Blob 来操做此文件。可是 Node.js 却没有实现这些 API,而是在文件系统之上构建了 Stream 模块来实现。再看看其服务器端编程语言例如 Java、PHP 也都提供了 Stream。

若是咱们把 Node.js 做为一个 Web 服务器,那么咱们横向和 Nginx 对比一下。若是使用 js 开发一个静态文件服务器,那么 Nginx 能够轻轻松松以十倍百倍的性能辗压 Node.js。

咱们能够从底层分析一下二者为什么相差悬殊。这里有几个知识点:

  • 用户空间
  • 内核空间
  • 进程上下文
  • 中断上下文
  • DMA
  • Zero Copy

为了安全考虑操做系统不容许用户代码直接操做硬件,为了保证操做系统内核的安全,将空间划分为两部分,一部分为内核空间,一部分为用户空间。用户编写的代码运行在用户空间,当须要使用底层功能时,能够经过系统调用进入内核,例如文件读取。

当用户进程经过系统调用从用户空间进入到内核空间时,系统须要将用户进程的上下文保存起来,当再次从内核空间回到用户空间时,系统恢复此上下文。

对于静态服务器,则这个步骤大概是:

  • 调用 read,文件被 copy 到内核缓冲区
  • read 函数返回,文件从内核缓冲区 copy 到用户缓冲区
  • write 函数调用,将文件从用户缓冲区 copy 到内核与 socket 相关的缓冲区
  • 数据从 socket 缓冲区 copy 到相关协议引擎

能够看到文件在整个过程当中被 copy 了 4 次。

而 Nginx 底层使用 sendfile,能够实现 Zero Copy (零拷贝)。

整个流程变成了:

  • sendfile 系统调用,文件被 copy 至内核缓冲区
  • 从内核缓冲区 copy 至内核中 socket 相关的缓冲区
  • 从 socket 相关的缓冲区 copy 到协议引擎

能够看到在这个过程当中,只有 3 次 copy。并且没有了用户空间和内核空间的切换,也不须要保存和恢复进程的上下文。其实上面还有优化的余地,由于在内核中发生了一次缓冲区到缓冲区的 copy。在 Linux 内核版本 2.4 以后,DMA 模块将数据直接从内核缓冲区传递给协议引擎。

虽然称为 Zero Copy,可是数据依然是从磁盘复制到了内存,从操做系统的角度来看这个是必须的,所谓的零拷贝是指内核中没有冗余数据,数据不须要在内核拷贝。借助 DMA 模块此过程彻底不须要 CPU 参与。

在 Nginx 中只须要数据副本的 2 个 copy,而 Node.js 则须要 4 次。若是 Node.js 要想使用 Zero Copy 也有方法,好比使用 os 模块的功能,或者直接使用 C++ 扩展。

从另外一个角度讲,Node.js 的性能损耗不只仅是 4 次 copy 以及进程上下文的保存和恢复,还包括数据和代码从 C++ 到 JavaScript 的反复跨越边界。

咱们回过头来讨论浏览器,对于浏览器来说,根本就不须要这个特性。由于浏览器中的 JavaScript 代码不只仅是在内核空间运行,并且仍是在沙盒空间运行。

因此与其在此猜想兼容浏览器指的什么,不如对比浏览器和服务器的差异:

  • 浏览器运行不受信代码,服务器运行受信代码
  • 浏览器遵循 W3/WHATWG,服务器遵循 POSIX
  • 浏览器关心 API 层的性能,服务器更关心操做系统层的性能
  • 浏览器能力受限,服务器能力不受限

扫码二维码关注个人公众号,每周推送原创前端内容

相关文章
相关标签/搜索