06.06 Node Bug 太多慘遭創始人拋棄,前端開發要變天?

曾經 Node 的面世,將 JavaScript 首次帶入了後端服務器端開發,不僅讓諸多的前端開發者更能輕而易舉地編寫出高性能的 Web 服務,同時也大大地提高了服務器的安全性。而如今經過九年的發展,其創始人 Ryan Dahl 不僅"嫌棄"了存在很多槽點的 Node,還重新發布了一個新的開源項目——Deno,而這究竟是怎麼一回事?Deno 會將 Node 取而代之嗎?對前端開發者的影響大嗎?接下來,我們將一一為大家解讀其中背後的故事。

Node Bug 太多慘遭創始人拋棄,前端開發要變天?

作者 | 屠敏

近日,在 2018 年的 JSConf 上,Node 之父 Ryan Dahl 發表了主題為《Design Mistakes in Node》的演講,在演講中,他為曾在 Node 設計上所犯的一些錯誤表示遺憾,併為此提出了一種新的原型設計思路,創建了一套立足於 V8 的安全 TypeScript 運行時項目——Deno

Node Bug 太多慘遭創始人拋棄,前端開發要變天?

Node 初始目標

對於 Node 最初創建的目標,主要是集中於編程事件驅動的 HTTP 服務器上。隨著時間的推移,後來也驗證了這一點對於當時服務器端 JavaScript 來說至關重要。遺憾的是,Node 後期並沒有得到很好的維護,因為在 2012 年,已經在這個項目上耗費了四年時光的 Ryan Dahl 認為 Node 已經實現了他的預期目標,如:

  • 支持多種協議:HTTP、SSL、......
  • 可運行於 Windows(使用 lOCP:http://tinyclouds.org/iocp-links.html)、Linux(epoll)、Mac(kqueue)上。
  • 具有穩定的 API。
  • 通過 NPM 實現增加外部模塊的生態系統。

且 Ryan Dahl 認為對於 Node 的後期也只需修復一下因不斷增加的代碼而出現的 Bug,於是他在 Node 如日中天時離開了 Node 團隊。直至最近,他才發現曾經的自己錯了,雖說當時 Node 已經為用戶提供了一套友好的非阻塞框架,但是後續還是出現了很多不可迴避的問題。

安全性不足

V8 本身是一個非常好的安全沙箱。如果當時能夠對某些特定應用程序的維護更加上心,也許 Node 可以實現比其他任何語言更好的安全保障。譬如,用戶的 linter 不應該具備完全訪問計算機和網絡的權限。

構建系統(GYP)

要知道構建系統是非常困難且重要的。最初 V8(藉助 Chrome)開始使用 GYP,而 Node 也對接了 GYP,但是後來 Chrome 放棄了 GYP 而轉向 GN,因此 Node 成為 GYP 的唯一用戶。對於 GYP 的繼續使用可能是 Node 核心最大的敗筆。

對此,Ryan Dahl 認為自己不應該引導開發者基於 V8 引擎使用 C++ 編寫,而是應該提供一個核心外部函數接口(FFI)。其實早前,就有很多人建議他轉向 FFI,但當時 Ryan Dahl 並沒在意,這讓他現在追悔莫及。

最後, Ryan Dahl 還對 libuv 採用 autotools 表示非常不滿意。

package.json

對於 NPM,雖然是 Isaac 創建了 package.json(絕大部分)。但最終是由 Ryan Dahl 通過了允許 Node 的 require() 函數來檢查 package.json 文件,將 NPM 包含在 Node 的發行版本中,使之成為現實中標準方案。然而,令人懊惱的是,這其中存在一個模塊的集中(私有控制)存儲庫。

即 require("somemodule") 並非唯一,它在很多地方都被定義了。

Node Bug 太多慘遭創始人拋棄,前端開發要變天?

此外,package.json 這一文件還衍生出“模塊”作為文件目錄的概念。這不是一種絕對必要的抽象機制,此前在 web 上也從未出現過。

如今的 package.json 文件中包含了各種不必要的信息。譬如許可、庫、描述等等。

如果在導入時僅使用相關文件和 URL,則路徑就可定義版本,也沒有必要列出依賴關係。

Node Bug 太多慘遭創始人拋棄,前端開發要變天?

node_modules

node_modules 極大地提高了模塊解析算法複雜度。vendored-by-default 初衷是好的,但是在實踐中,僅使用 $NODE_PATH 並不能實現預期的目的。它偏離了瀏覽器語義。

Ryan Dahl 表示這是他的錯,且遺憾的是,這一問題如今也無法彌補。

require("module") 沒有 ".js"擴展名

在腳本標籤的 src 屬性中,“.js”不容忽視,而在 require("module") 中沒有明確地顯示出 .js 擴展名。

index.js

因為已有 index.html 文件的存在,index.js 則會給模塊加載系統帶來不必要的複雜因素。且在已受 package.json 支持下,它將變得毫無意義。

Deno:一套立足於 V8 的安全 TypeScript 運行時

以上這些問題不僅成為其創始人 Ryan Dahl “嫌棄” Node 的原因,同時也為諸多開發者帶來不少的麻煩。基於此,Ryan Dahl 使用 Go 語言代替 C++ 重新編寫跨平臺底層內核驅動,上層仍使用 V8 引擎,發佈了一套安全 TypeScript 運行時項目——Deno。其主要目標如下:

安全

利用 JavaScript 是安全沙箱的這一事實:

  • 默認情況下,應該在沒有任何網絡或文件系統寫權限的情況下運行腳本;
  • 用戶可以選擇通過標誌訪問:--allow-net --allow-write
  • 允許用戶運行不受信任的實用程序(如 linter)

不允許將任意本地函數綁定到 V8 中:

  • 所有的系統調用都是通過消息傳遞完成的(protobuf 序列化)
  • 確切地說有兩個本地函數:send 和 recv
  • 這既簡化了設計,又使系統更易於審核。
Node Bug 太多慘遭創始人拋棄,前端開發要變天?

簡化模塊系統

  • 不再嘗試與現有 Node 模塊兼容;
  • 導入只是相對或絕對URL;
import {test} from "https://unpkg.com/[email protected]/test.ts
import {log} from "./util.ts"
  • import 必須提供擴展;
  • 通過遠程 URL 方式引入依賴而非通過本地模塊,且在第一次運行時進行加載和緩存。只有在使用 --reload 運行,依賴才會更新。
  • 可以通過指定非默認緩存目錄來完成交付。

將 TypeScript 編譯器內置於可執行文件當中

TS 很強大:

  • 它終於實現了一種實用的可選類型語言。
  • 且代碼從快速構建到大型架構有良好的擴展。

Deno 將掛鉤到 TS 編譯器中, 以實現模塊解析和構建結果的增量緩存。未修改的 TS 文件不能再重新編譯。此外,普通的 JS 也可以工作(道理很簡單,因為 TS 是 JS 的超集)。最後應該使用 V8 快照來實現快速啟動(目前原型設計還沒有這一功能)。

以最小的關聯運行一個可執行文件

> ls -lh deno
-rwxrwxr-x 1 ryan ryan 55M May 28 23:46 deno
> ldd deno
linux-vdso.so.1 => (0x00007ffc6797a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f104fa47000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f104f6c5000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f104f3bc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f104f1a6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f104eddc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f104fc64000)

發揮 2018 年的技術優勢

通過使用 Parcel 將編譯 Node 模塊打包,引導運行。(這將大大地簡化 Node 流程 )。

良好的基礎架構現在存在於本地代碼中,EG 不需要再為 HTTP 擔心。 已有其他機制負責實現相關功能(Node 中的情況並非如此,Web 服務器還需要 100% 的手動滾動)。

目前 Deno 的非 JS 部分正在使用 Go 語言編寫,對於替代語言:

  • Rust 或許是一個不錯的選擇;
  • 如果允許其他人以 Go 或 Rust 語言編寫自己的 Deno 項目,C++ 可能會是一個不錯的選擇?

Deno 的發佈對開發者意味著什麼?

Deno 提高了安全性、簡化了模塊系統、面向 TypeScript,換句話說 Deno 主要是針對 Node 的痛點才出現的,那麼 Deno 是否會取代以根深蒂固的 Node 呢?初學者是從 Deno 入手還是 Node?

對此,Ryan Dahl 表示,當然使用 Node,因為 Node 和 Deno 兩者最大的區別是 Node 早已大行其道,而 Deno 開發僅有一個月的時間,還在初級階段,僅是個 Demo 根本無法投入使用。因此,Deno 想要在短時間之內將 Node 取而代之也是不可能的。

  • Deno:https://github.com/ry/deno
  • PPT:http://tinyclouds.org/jsconf2018.pdf


分享到:


相關文章: