Rust 是 JavaScript 基礎設施的未來

語言: CN / TW / HK

本文翻譯自: Rust Is The Future of JavaScript Infrastructure – Lee Robinson [1] ,已獲得作者授權,原文略做修改以符合中文語境。

(圖片鎮樓,與原文無關)

Rust [2] 是一種快速、可靠、記憶體高效的程式語言。它已經連續六年被評為最受 [3] [4] [5] [6] [7] [8] 。它由 Mozilla 建立,現在被 Facebook [9]蘋果 [10]亞馬遜 [11]微軟 [12]谷歌 [13] 用於系統基礎設施、加密、虛擬化和更多底層(low-level)的程式設計中。

為什麼Rust現在被用來取代 JavaScript 成為 Web 生態系統的一部分,如壓縮(Terser)、編譯(Babel)、格式化(Prettier)、打包(webpack)、linting(ESLint),以及其他場景?

什麼是Rust?

Rust 幫助開發人員編寫執行快並高效利用記憶體的軟體。它是 C++ 或 C 等語言的現代替代品,聚焦在程式碼安全和簡潔的語法。

Rust 與 JavaScript 有很大不同。JavaScript 採用的是 垃圾回收 [14] 機制,會試圖清除不再使用的變數和物件。JavaScript 將開發者從對手動記憶體管理的思考中抽離出來。

有了 Rust,開發者對記憶體分配有了更多的控制,而不像 C++ 或 Go 那樣令人痛苦。

Rust 使用了一種相對獨特的記憶體管理方法,包含了記憶體“所有權”的概念。基本上,Rust 會記錄誰可以讀取和寫入記憶體。它知道程式什麼時候在使用記憶體,一旦不再需要就立即釋放記憶體。它在編譯時執行記憶體規則,使得執行時的記憶體錯誤幾乎不可能出現。你不需要手動跟蹤記憶體。編譯器會照顧到這一點。

—— Discord [15]

Adoption

在上面提到的公司之外,Rust 還被用於流行的開源庫,比如:

  • Firecracker [16] (AWS)

  • Bottlerocket [17] (AWS)

  • Quiche [18] (Cloudflare)

  • Neqo [19] (Mozilla)

Rust 一直是我們團隊的力量源泉,押注Rust是我們做出的最好決定之一。除了效能之外,它的人機工程學( ergonomics )和對正確性的關注也幫助我們控制了同步的複雜性。我們可以在型別系統中對系統的複雜不變性進行編碼,讓編譯器為我們檢查。

—— Dropbox [20]

從 JavaScript 到 Rust

JavaScript 是使用最廣泛的程式語言,存在於每個有瀏覽器的裝置上。在過去的十年中,圍繞著 JavaScript 已經建立了一個龐大的生態系統:

  • Webpack:開發者希望將多個 JavaScript 檔案 bundle 成一個檔案。

  • Babel:開發者希望在支援舊版瀏覽器的同時編寫現代 JavaScript 。

  • Terser:開發者希望生成儘可能小的檔案。

  • Prettier:開發者希望有一個有自帶規則(opinionated)的程式碼格式化器,剛好可用就行。

  • ESLint:開發者希望在部署前發現他們的程式碼存在的問題。

數以百萬計的程式碼被編寫出來,甚至更多的 bug 被修復,從而為今天的 Web 應用提供了基礎。所有這些工具都是用 JavaScript 或 TypeScript 編寫的。目前已經做的很不錯了,但我們對 JS 的優化已經達到頂峰。因此,這激發了一類新的工具們的誕生,旨在極大地提高 Web 構建的效能。

SWC

SWC [21] 創建於 2017 年,一個下一代快速開發的工具,是一個基於 Rust 的可擴充套件平臺。Next.js、 Parcel 和 Deno 等工具,以及 Vercel、位元組跳動、騰訊、Shopify 等公司都在使用它。

SWC 可用於編譯(compilation)、壓縮(minification)、打包(bundling)等 —— 並且被設計成可擴充套件的。你可以呼叫它來執行程式碼轉換(無論是內建的還是自定義的)。這些轉換由更高維度的工具來執行,比如 Next.js 。

Deno

Deno [22] 創建於 2018 年,是一個簡單、現代、安全的 JavaScript 和 TypeScript 的執行時,Deno 使用 V8 [23] 的同時,並以 Rust 構建。它試圖取代 Node.js ,由 Node.js 的原作者建立。雖然它是在 2018 年建立的,但直到 2020 年 5月才達到 [24] v1.0 [25]

Deno 的 linter、code formatter 和文件生成器是使用 SWC 構建的 [26]

esbuild

esbuild [27] 創建於 2020 年 1 月,一個程式碼打包和壓縮的工具,它比當今用 Go 寫的工具快 10 - 100 倍

我試圖建立一個構建工具:

A)能夠在一個合理的場景(bundler JavaScript,TypeScript,也許還有CSS)中工作得很好。

B)能夠重新定義社群對構建工具速度的期望。對於JS快速構建工具來說,到底什麼才是快?在我看來,我們目前的工具都太慢了。

—— Evan,Creator of esbuild( Source [28]

在 esbuild 釋出之前,用系統程式語言(如 Go 和 Rust )構建 JavaScript 工具是相當小眾的。因此在我看來,esbuild 激發人們對於讓開發工具更快的廣泛興趣。Evan 選擇了使用 Go:

Rust版本也許可以通過足夠的努力使其以同等速度工作。但在高層次上,Go 的工作方式更令人愉快。這是一個 side project ,所以它對我來說必須要有樂趣。

—— Evan,Creator of esbuild( Source [29]

有人認為 Rust 可以表現得更好,但兩者都可以實現 Evan 最初的目標,即影響社群:

即使只是進行了基本的優化,Rust也能夠勝過超手工調整的 Go 版本。這是一個巨大的證明,與我們不得不對 Go 的深入研究相比,用Rust編寫高效程式是多麼容易。

—— Discord [30]

Rome

Rome [31] 創建於 2020 年 8 月,包含 linter、compiler、bundler、test runner 以及其它東西,適用於 JavaScript、TypeScript、HTML、JSON、Markdown 和 CSS 。他們的目標是取代和統一整個前端開發工具鏈。它是由 Sebastian [32] 建立的,他是 Babel 的建立者。

那麼,為什麼要重寫一切呢?

對 Babel 進行必要的修改,使其成為其他工具的可靠基礎,這絕對需要對所有東西進行修改。這個架構與我在 2014 年學習解析器、 AST 和編譯器時做出的最初設計選擇是有緊密聯絡的。

—— Sebastian( Source [33]

Rome 目前是用 TypeScript 編寫的,在 Node.js 上執行。但他們現在正致力於 用 Rust [34] 重寫 [35]

NAPI

Rust 與 Node.js 的整合比其他低階語言更好。

napi-rs [36] 允許你用 Rust 構建預編譯的 Node.js add-ons 。它為交叉編譯(cross-compilation)和向 NPM 釋出本地二進位制檔案提供了一個開箱即用的解決方案,不需要 node-gyp 或使用 postinstall

相應的,你也能輕鬆構建一個被 Node.js 側直接呼叫的 Rust 模組,而不需要像 esbuild 那樣建立一個子程序。

Rust + WebAssembly

WebAssembly [37] (WASM)是一種可移植的低階語言,Rust 可以編譯成它。它在瀏覽器中執行,可與 JavaScript 互操作,並被所有主要的現代瀏覽器所支援。

WASM 肯定比 JS 快很多,但還沒有達到原生速度。在我們的測試中,Parcel 編譯成 WASM 後的執行速度比使用本地二進位制檔案慢 10 - 20 倍。

—— Devon Govett [38]

雖然 WASM 還不是完美的解決方案,但它可以幫助開發者創建極快的 Web 體驗。Rust 團隊 致力於 [39] 實現高質量和先進(cutting edge)的 WASM 實現。對於開發者來說,這意味著你可以擁有 Rust 的效能優勢(相對於 Go ),同時還可以為 Web 服務(使用 WASM )。

這個領域的一些早期庫和框架:

  • Yew [40]

  • Percy [41]

  • Seed [42]

  • Sycamore [43]

  • Stork [44]

這些基於 Rust 的、可編譯為 WASM 的 Web 框架並不是要取代 JavaScript,而是要與之一起工作。雖然我們還沒有達到這個目的,但看到 Rust 在兩方面都追隨 Web 的發展是很有趣的:使現有的 JavaScript 工具更快,並在未來提出 編譯到 WASM [45] 的想法。

這就是 Rust 之後的路。

為什麼不選擇 Rust ?

Rust 有一個陡峭的學習曲線。它的抽象程度比大多數 Web 開發者所習慣的要低。

Rust 會迫使你思考你程式碼中對系統程式設計方面具有很大影響的部分。它讓你思考記憶體是如何共享或複製的。它讓你思考真實但不可能發生的邊界問題,並確保它們得到處理。它可以幫助你寫出在所有可能的方面都非常高效的程式碼。

—— Tom MacWright ( Source [46] )

此外,Rust 在網路社群的使用仍然是小眾的。它還沒有達到技術選型臨界點(critical adoption)。即使學習 Rust 的 JavaScript 工具會有一定的門檻,但有趣的是,開發者寧願擁有一個 更快、更難參與貢獻 [47] 的工具。 唯快不破 [48] (Fast software wins) [49]

目前,你很難為你喜歡的服務(如登入鑑權、資料庫、支付等工作)找到一個 Rust 庫或框架。我確實認為,一旦 Rust 和 WASM 達到技術選型臨界點(critical adoption),這個問題會自行解決。但現在還不行。 我們需要現有的 JavaScript 工具來幫助我們縮小差距,並逐步採用效能改進。

JavaScript 工具化的未來

我相信 Rust 是 JavaScript 工具化的未來。 Next.js 12 [50] 已經開始了我們的轉型,用 SWC 和 Rust 完全取代 Babel(transpilation)和 Terser(壓縮)。為什麼會有這樣的選擇?

  • 可擴充套件性(Extensibility)。SWC 可以作為 Next.js 內部的一個 Crate 使用,而無需 fork 其它庫或面臨設計上的限制(workaround design constraints)。

  • 效能(Performance)。通過改用 SWC ,我們在 Next.js 中實現了約 3 倍的重新整理速度(Fast Refresh)和約 5 倍的構建速度,還有更多的優化正在進行。

  • WebAssembly。Rust 對 WASM 的支援,使得 Next.js 可以支援所有可能的平臺,讓 Next.js 遍佈所有的地方。

  • 社群(Community)。Rust 社群和生態系統是驚人的,而且還在不斷增長。

在逐步使用 SWC 的絕不僅僅是 Next.js:

  • Deno [51] linter、程式碼格式化器和文件生成器都是用 SWC 構建的 [52]

  • Rome [53] 正在 用 Rust 重寫 [54] ,並計劃使用 SWC 。

  • dprint [55] ,建立在 SWC 之上,一個快 30 倍的用於替代 Prettier 的程式碼格式化工具。

  • Parcel [56] 使用 SWC 將整體構建效能 提高了 10 倍 [57]

Parcel 像一個庫一樣使用 SWC 。之前我們使用 Babel 的解析器和用 JS 編寫的自定義轉換。現在,我們使用 SWC 的解析器和 Rust 中的 自定義轉換 [58] 。這包括一個全域性 hoisting 的實現、依賴性收集等。它的範圍類似於 Deno 在 SWC 之上的構建方式。

—— Devon Govett [59]

現在是 Rust 的早期階段 —— 有幾個重要的部分還在摸索之中:

  • 外掛(Plungins)。對於許多 JavaScript 開發者來說,用 Rust 編寫外掛並不是那麼容易的。同時,在 JavaScript 中暴露一個外掛系統可能會否定效能的提升。目前還沒有一個明確的解決方案。

  • 打包(Bundling)。一個有趣的發展領域是 swcpack ,它是 SWC 對 Webpack 的替代。它仍在開發中,但可能是非常有前途的。

  • WebAssembly。如上所述,編寫 Rust 並編譯成 WASM 的前景很誘人,但仍有工作要做。

不管怎麼說,我相信 Rust 會在未來 1 - 2 年以及未來繼續對 JavaScript 生態系統產生重大影響。想象一下這樣一個世界:Next.js 中使用的所有構建工具都是用 Rust 編寫的,給你帶來最佳效能。然後,Next.js 可以作為一個 靜態二進位制檔案 [60] (static binary)分發,你可以從 NPM 下載。

這就是我想生活(和建設)的世界。

感謝 Devon Govett [61] 審閱本文的早期草稿。

全文完

活動推薦:

一個是前 Facebook 程式設計師,一個是在中國遠端的現Facebook程式設計師,兩位都研究過開發程式語言,兩位都是在開發領域有所建樹的程式設計師大佬,趙海平 與 張巨集波與你聊聊以往經歷,聊聊職業發展,聊聊程式語言~ 11月16號 (週二), 17:00 - 19:00,掘金直播間,海平和巨集波與你不見不散~

直播地址:point_right:: https://live.juejin.cn/4354/rescript-lang [62]

:point_down: 掃碼回覆 “程式語言”,入群交流

參考資料

[1]

Rust Is The Future of JavaScript Infrastructure – Lee Robinson: https://leerob.io/blog/rust

[2]

Rust: https://www.rust-lang.org/

[3]

歡: https://insights.stackoverflow.com/survey/2016#technology-most-loved-dreaded-and-wanted

[4]

迎: https://insights.stackoverflow.com/survey/2017#most-loved-dreaded-and-wanted

[5]

編: https://insights.stackoverflow.com/survey/2018#technology-_-most-loved-dreaded-and-wanted-languages

[6]

程: https://insights.stackoverflow.com/survey/2019#technology-_-most-loved-dreaded-and-wanted-languages

[7]

語: https://insights.stackoverflow.com/survey/2019#technology-_-most-loved-dreaded-and-wanted-languages

[8]

言: https://insights.stackoverflow.com/survey/2020#most-loved-dreaded-and-wanted

[9]

Facebook: https://engineering.fb.com/2021/04/29/developer-tools/rust/

[10]

蘋果: https://twitter.com/oskargroth/status/1301502690409709568

[11]

亞馬遜: https://aws.amazon.com/blogs/opensource/why-aws-loves-rust-and-how-wed-like-to-help/

[12]

微軟: https://twitter.com/ryan_levick/status/1171830191804551168

[13]

谷歌: https://security.googleblog.com/2021/04/rust-in-android-platform.html

[14]

垃圾回收: https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)

[15]

—— Discord: https://blog.discord.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f

[16]

Firecracker: https://github.com/firecracker-microvm/firecracker

[17]

Bottlerocket: https://github.com/bottlerocket-os/bottlerocket

[18]

Quiche: https://github.com/cloudflare/quiche

[19]

Neqo: https://github.com/mozilla/neqo

[20]

—— Dropbox: https://dropbox.tech/infrastructure/rewriting-the-heart-of-our-sync-engine

[21]

SWC: http://swc.rs/

[22]

Deno: https://deno.land/

[23]

V8: https://v8.dev/

[24]

5月才達到: https://deno.com/blog/v1

[25]

v1.0: https://deno.com/blog/v1

[26]

SWC 構建的: https://twitter.com/devongovett/status/1369033422002389000

[27]

esbuild: https://esbuild.github.io/

[28]

Source: https://news.ycombinator.com/item?id=22336334

[29]

Source: https://news.ycombinator.com/item?id=22336284

[30]

—— Discord: https://blog.discord.com/why-discord-is-switching-from-go-to-rust-a190bbca2b1f

[31]

Rome: https://rome.tools/blog/2020/08/08/introducing-rome

[32]

Sebastian: https://twitter.com/sebmck

[33]

Source: https://rome.tools/blog/2020/08/08/introducing-rome

[34]

用 Rust: https://twitter.com/rometools/status/1422616144763097091

[35]

重寫: https://twitter.com/rometools/status/1422616144763097091

[36]

napi-rs: https://napi.rs/

[37]

WebAssembly: https://webassembly.org/docs/use-cases/

[38]

Devon Govett: https://twitter.com/devongovett

[39]

致力於: https://www.rust-lang.org/what/wasm

[40]

Yew: https://yew.rs/

[41]

Percy: https://github.com/chinedufn/percy

[42]

Seed: https://github.com/seed-rs/seed

[43]

Sycamore: https://github.com/sycamore-rs/sycamore

[44]

Stork: https://stork-search.net/

[45]

編譯到 WASM: https://rustwasm.github.io/docs/book/introduction.html

[46]

Source: https://macwright.com/2021/01/15/rust.html

[47]

更快、更難參與貢獻: https://twitter.com/devongovett/status/1261379312898306048

[48]

唯快不破: https://craigmod.com/essays/fast_software/

[49]

Fast software wins): https://craigmod.com/essays/fast_software/

[50]

Next.js 12: http://nextjs.org/12

[51]

Deno: https://deno.land/

[52]

SWC 構建的: https://twitter.com/devongovett/status/1369033422002389000

[53]

Rome: https://rome.tools/

[54]

用 Rust 重寫: https://twitter.com/rometools/status/1422616144763097091

[55]

dprint: https://github.com/devongovett/dprint-node

[56]

Parcel: https://parceljs.org/

[57]

提高了 10 倍: https://v2.parceljs.org/blog/beta3/

[58]

自定義轉換: https://github.com/parcel-bundler/parcel/tree/v2/packages/transformers/js/core/src

[59]

Devon Govett: https://twitter.com/devongovett

[60]

靜態二進位制檔案: https://en.wikipedia.org/wiki/Static_build

[61]

Devon Govett: https://twitter.com/devongovett

[62]

https://live.juejin.cn/4354/rescript-lang: https://live.juejin.cn/4354/rescript-lang