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 層的性能,服務器更關心操做系統層的性能
  • 瀏覽器能力受限,服務器能力不受限

掃碼二維碼關注個人公衆號,每週推送原創前端內容

相關文章
相關標籤/搜索