摘要:里面有一句描述,可以看到的目標是兼容瀏覽器。那么這里的兼容瀏覽器到底如何是什么意思呢我簡單談談我的理解吧。很多人還有誤解以為兼容瀏覽器指的是會提供類似里的寫法。
Deno 里面有一句描述:"Aims to be browser compatible",可以看到 Deno 的目標是兼容瀏覽器。那么這里的兼容瀏覽器到底如何是什么意思呢?
我簡單談談我的理解吧。
首先這里的兼容性肯定不是 Deno 直接在瀏覽器端運行。因為 Deno 是一個和瀏覽器平級的 Runtime。
很多人還有誤解以為兼容瀏覽器指的是 Deno 會提供“類似 Node.js 里的 UMD 寫法”。首先我們明確一點,這里的兼容不是單指語法層面的兼容,并不是說要兼容 ES3 ES5。所以不要產生這種誤解,以為可以通過 babel 兼容 Node.js 和 Deno。
在 Deno 的 Roadmap 里面作者就已經寫到了:
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:
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 和瀏覽器的定位很像。
V8 團隊的一個錯誤,使得整個互聯網變慢
因為我們可以看到,兼容服務器端生態和兼容瀏覽器端生態的一個區別:
瀏覽器里面運行的都是不受信代碼
服務器運行的是受信代碼
我們再換一個角度聊聊服務器生態。
很多人還有一個誤解,就是覺得上面提到的那些 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 層的性能,服務器更關心操作系統層的性能
瀏覽器能力受限,服務器能力不受限
掃碼二維碼關注我的公眾號,每周推送原創前端內容
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95882.html
摘要:長文預警字,圖。開發并不是因為,也不是為了取代。不知道從官方介紹來看,可以認為它是下一代是如何腦補出來的。只是一個原型或實驗性產品。所以,不是要取代,也不是下一代,也不是要放棄重建生態。的目前是要擁抱瀏覽器生態。 這幾天前端圈最火的事件莫過于 ry(Ryan Dahl) 的新項目 deno 了,很多 IT 新聞和媒體都用了標題:下一代 Node.js。這周末讀了一遍 deno 的源碼,...
摘要:自發布以來就備受關注,也有很多媒體和開發者稱為下一代。所以在寫這個插件之前,我又為寫了一個插件。插件提供了開箱即用的支持,開發者不需要任何配置,但是有一個前提是開發者需要使用內置的。 這幾天為 Deno 開發了一個 VS Code 插件:Deno support for VSCode,GitHub 地址:https://github.com/justjavac/...。 自 Deno ...
摘要:理解基礎篇原理篇一啟動加載通信方式執行代碼和相似,包含同步和異步的方式,異步方式通過的實現。同時在異步通信完成后,會創建一個對象,將作為,作為,加入中。 理解deno-基礎篇deno-原理篇一啟動加載 通信方式 deno執行代碼和node相似,包含同步和異步的方式, 異步方式通過async的實現。 Typescript/Javascript調用rust 在上一節中講到deno的啟動時會...
摘要:介紹是一個基于和的的安全運行時。文件中主要是的代碼,是功能的具體實現。圖來自于官網,圖的架構圖預告接下來還會有兩篇文章分析的內部原理 deno介紹 deno是一個基于v8、rust和Tokio的Javascript/Typescript的安全運行時。它在內部嵌入了一個typescript的編譯器。可以將typescript編譯成js然后運行在v8上,并通過c++ libdeno實現js...
摘要:不知不覺中,已經默默的發布了個版本了昨晚通宵做了一個多版本的管理工具。地址功能基本參考了。安裝使用在平臺需要使用管理員權限打開命令行或者示例列出所有已安裝版本前面的星號表示當前正在使用的版本。切換版本目前功能比較簡陋,也不少,歡迎 不知不覺中,deno 已經默默的發布了 3 個版本了: 0.1.0 0.1.1 0.1.2 昨晚通宵做了一個 deno 多版本的管理工具: dvm。 g...
閱讀 1771·2021-11-25 09:43
閱讀 15325·2021-09-22 15:11
閱讀 2623·2019-08-30 13:19
閱讀 2009·2019-08-30 12:54
閱讀 1815·2019-08-29 13:06
閱讀 923·2019-08-26 14:07
閱讀 1612·2019-08-26 10:47
閱讀 3027·2019-08-26 10:41