天天看點

重新構想前端開發!Kotlin 新功能:無需了解Kotlin和JavaScript

作者 | 褚杏娟、核子可樂

近日,JetBrains 釋出了Kotlin 1.8.20 beta 版本,其中包括一項名為“Kotlin/Wasm”的實驗性功能,明确将 WebAssembly 設為編譯目标。據介紹,新版本依賴于原生 Wasm 垃圾收集功能 WasmGC,後者同樣處于早期開發階段。

JetBrains 總結了 Kotlin/Wasm 的優勢:

  • 與 wasm32 Kotlin/Native 目标相比,Kotlin/Wasm 的編譯速度更快,因為後者不必使用 LLVM。
  • 由于 Wasm 垃圾收集支援,與 wasm32 目标相比,Kotlin/Wasm 與 JS 的互操作性、與浏覽器的內建更容易。
  • 與 Kotlin/JS 和 JavaScript 相比,Kotlin/Wasm 應用程式啟動時間可能更快,因為 Wasm 具有緊湊且易于解析的位元組代碼。
  • 與 Kotlin/JS 和 JavaScript 相比,Kotlin/Wasm 應用程式運作時性能更快,因為 Wasm 是一種靜态類型語言。

不過,目前還沒有 IDE 為 Kotlin/Wasm 提供支援。JetBrains 在版本發行說明中提到,“我們以開箱即用的形式,為 Kotlin/Wasm 提供 Kotlin 标準庫(stdlib)和測試庫(kotlin/test)。”

重新構想前端開發!Kotlin 新功能:無需了解Kotlin和JavaScript

浏覽器中運作的 Kotlin/Wasm 示範

此前,通過基于 LLVM 的 Kotlin-Native 編譯指向和 LLVM Wasm 支援,Kotlin 已經能夠在某種程度上實作向 Wasm 的編譯,這種舊方法被稱為 wasm32。随着新版本的釋出,該方法将成為被棄用的多種 Kotlin/Native 編譯目标之一。

作為一種 JVM 語言,Kotlin 具備垃圾收集機制,但此前 Wasm 一直無法原生支援垃圾收集,這就要求各垃圾收集語言自行提供解決方案。Wasm-gc 就是其中一項提案,承諾“對進階語言做出有效支援”。此次,這一設計有望超越自定義解決方案,并減少應用程式的二進制檔案大小。Wasm-gc 可通過浏覽器 Flag 在最新版本的 Chrome、Firefox 和 Edge 上啟用。

Kotlin 的“通用型語言”理想

早在 2017 年,主流浏覽器都已經支援 WebAssembly。随着 WebAssembly 的蓬勃發展,各種程式設計語言也在增加對其的支援。比如,C/C++、Rust、Golang 等已支援将語言編譯到 WebAssembly 目标平台,Lua、JavaScript、Ruby 和 Python 等支援将語言的虛拟機或解釋器編譯到 WebAssembly 平台。

2021 年,WebAssembly 開源項目開始支援 GC(垃圾回收器),為實作 WebAssembly 支援像 Java、Kotlin 這樣的前端語言做準備。同年,Kotlin 程式語言開發團隊更新了發展路線,其中的一個重點就是增加 WebAssembly 支援。

Kotlin 總項目經理 Egor Tolstoy 表示,他們認為 WebAssembly 會成為未來建立豐富網頁應用程式的新标準,而 Kotlin 必需要能夠完美的提供支援。是以官方火力全開,組建了一個專門團隊來開發 Kotlin/Wasm 工作,并且與 WebAssembly 垃圾回收提案作者緊密合作,要實作 Kotlin 語言的基本功能、函數庫和基本 Gradle 的支援,還要添加實驗性 JavaScript 互通操作功能。

Kotlin 在 2017 Google 發表聲明後總被當成是安卓專用開發語言,但實際上,Kotlin 正在積極地向多平台語言演進,即“通用型語言”。

如今,JetBrains 提供了多個支援多平台的庫,如 kotlinx.coroutines、kotlinx.serialization、kotlinx-datetime。而 Kotlin 社群也緊跟着這樣的趨勢發展,出現了愈來愈多的庫、架構來支援多平台,如 Arrow、Okio、Apollo 等在新版本中都支援了多平台開發。

Kotlin/Wasm 究竟有什麼潛力

在最初的設計中,WebAssembly 隻是 C、C++或 Rust 這些低級語言的編譯目标。至于 Python、Ruby 甚至是 JavaScript 等動态語言,能充當解釋性的虛拟機即可。

但 WebAssembly 垃圾收集(GC)的貢獻者們正努力把它打造成垃圾收集語言(例如 Java、Kotlin 或 Dart)的編譯目标,并停止使用 JavaScript 作為 Web 位元組碼。此外,他們還考慮把其他語言也都轉化成前端開發中的理想選項,而不必像 TypeScript 那樣把一切先編譯成 JavaScript。

請注意,這些語言已經能夠在各個應用程式内提供自己的自定義垃圾收集,借此實作對 WebAssembly 的編譯。這樣做的缺點就是這樣生成的工件會更大,是以也不知道 WasmGC 真正推出時,原來的這種處理方式還有沒有競争力。

WasmGC 的實作源自 Chrome、Firefox、Edge 和 Safari 四大浏覽器的一個持續性項目,目前需要使用 Flag 加以啟用(例如,在 Chrome 或 Edge 上,需要使用--js-flags=--experimental-wasm-gc 指令行參數)。正是因為達不到開箱即用的程度,是以該技術目前還沒能得到廣泛采用。

但是,當 WasmGC 步入第四階段并在大多數浏覽器中實作開箱即用後,能夠利用 WasmGC 的語言将迎來顯著的競争優勢。

在 VMware 從事 Spring Framework 工作的 Sébastien Deleuze 稱,Kotlin/Wasm 很早就在關注 WasmGC,谷歌也在使用 J2CL 和 Dart 在 Google Sheets 中将 Java 編譯為 WasmGC。

前端(及全棧)開發

“因為要求開發者同時了解 Kotlin 和 JavaScript 兩套生态系統,是以我個人一直對 Kotlin/JS 不太感冒,但 Kotlin/Wasm 确實是個重塑前端開發面貌的好機會。”Deleuze 表示,“當然,Kotlin/Wasm 必須要提供良好的 JavaScript 互操作性(它也确實做到了),并作為可選項。”

目前,Kotlin/Wasm 提供 DOM API,是以某些 Kotlin/Wasm 前端架構可能已經足夠成為前端開發的理想選擇。Deleuze 表示自己可能也會試試将 Kotlin/Wasm 用于前端開發,再配合 Spring Boot Kotlin/JVM 後端實作 Kotlin 中的全棧開發。

但從另一個角度來看,WebAssembly 還有更多值得發掘的亮點。如果 Compose for Web(Android 上使用的多平台版 Jetpack Compose)能夠用 Kotlin/Wasm 代替 Kotlin/JS 來完美執行基于 Canvas 的像素渲染,結果又會如何?(稍做劇透,其實已經實作了。)

如果 Kotlin/Wasm 能夠用 WebAssembly 來取代 JavaScript,支援一種新的 Jamstack 架構,結果又會如何?

WebAssembly 元件模型

要想充分了解 Kotlin/Wasm 的巨大潛力,就不能不提 WebAssembly 元件模型。正是它的存在,讓我們能使用任意支援 WebAssembly 的語言,為 WebAssembly 開發元件。這項工作的基石正是 WIT 格式,可用于描述導入和展出并生成特定于語言的 binding。

Deleuze 親自實踐了一下,看看 WIT 是如何被轉譯成 Kotlin 的,結果看起來還不錯。例如,其嘗試将 WIT variant 定義為:

variant filter {
    all,
    none,
    some(list<string>),
 }           

複制代碼

轉譯出的 Kotlin 代碼如下:

sealed interface Filter {
   object All : Filter
   object None : Filter
   class Some(val value: List<String>): Filter
}           

複制代碼

利用 String 提供的 null 安全特性,WIT option<string> 能夠被準确轉譯為 Kotlin 慣用的選項值處理方式。在 Deleuze 看來,Kotlin 協程也将成為元件模型異步支援綁定中一個強大的競争優勢。

用 warg 實作 WebAssembly 包管理

大家可能會好奇 WebAssembly 要如何釋出和使用。别擔心,面向 WebAssembly 包的标準化管理項目 Warg,有望帶來各種包 repo 執行個體,其中的關鍵就是 WebAssembly 包 repo 将支援多語言。

沒錯,Maven Central 或者 NPM 在 Java 和 JavaScript 之外的語言中也有使用,但無論是生産還是消費都擺脫不了“二等公民”的陰影。Warg 和 WebAssembly 将真正把多語言元件推向全新的高度。

Deleuze 預測,像 Rust/C/C++這樣的語言将主要用于生産 Wasm 元件(強調效率,隻為非共享方法提供極小、甚至幹脆不提供運作時);而 Kotlin/Wasm 這類能利用 WasmGC 的語言,則主要負責建構使用這些元件的應用程式。當然,Rust 也可以用來開發 Wasm 應用程式,但 Deleuze 猜測 WasmGC 語言才是這類用例中的主導者。

WASI

所謂 WASI,簡言之就是在定義标準化系統接口(包括檔案系統、時鐘、環境變量、指令行參數或者标準輸入/輸出)應該如何被公開給 Wasm 應用程式。機器學習、人工智能或者雲存儲等其他用例也可以通過 WASI 進行标準化。

Kotlin/Wasm 目前還不支援 WASI,但開發團隊已經提供低級 API 實作。有趣的是,隻需要提供 WASI 平台中的特定部分,就能使用 Kotlin 的多平台庫(例如 kotlinx-datetime 或 Okio)。

“ Kotlin/Wasm + WASI ”将并發出驚人的潛能:它可以提供 Kotlin/JVM 的替代方案,将應用程式部署到雲端、邊緣甚至是 Serverless 函數的形式;也被大量用作容器鏡像的替代方案,能在幾微秒内完成執行個體化、提供更高的安全性且不依賴于任何特定硬體或作業系統。這樣的特性可能讓人想起 Java 在 1995 年提出的“一次編寫,随處運作”(WORA)口号。

目前實作這一願景的主要障礙在于,Wasmtime 等純 WASI 運作時還不支援 WasmGC。目前,運作 Kotlin/Wasm WASI 應用程式的主要途徑是利用 Node WASI 支援。

附:如何啟用 Kotlin/Wasm

要啟用 Kotlin/Wasm 并對其進行測試,請更新您的 build.gradle.kts 檔案:

plugins {
    kotlin("multiplatform") version "1.8.20-Beta"
}




kotlin {
    wasm {
        binaries.executable()
        browser {
        }
    }
    sourceSets {
        val commonMain by getting
        val commonTest by getting {
            dependencies {
                implementation(kotlin("test"))
            }
        }
        val wasmMain by getting
        val wasmTest by getting
    }
}           

複制代碼

可檢視包含 Kotlin/Wasm 示例的 GitHub 存儲庫

要運作 Kotlin/Wasm 項目,您需要更新目标環境的設定:

  • Chrome,對于版本 109 或更高版本:
  1. 在您的浏覽器中轉到 chrome://flags/#enable-webassembly-garbage-collection。
  2. 重新啟動浏覽器應用程式。
  • Firefox,對于版本 111 或更高版本:
  1. 在您的浏覽器中轉到 about:config。
  2. 啟用 javascript.options.wasm_function_references 和 javascript.options.wasm_gc 選項。
  3. 重新啟動浏覽器應用程式。
  • Edge,對于版本 109 或更高版本:

使用指令行參數運作應用程式-- js-flags=--experimental-wasm-gc。

參考連結:

https://devclass.com/2023/02/14/kotlin-debuts-experimental-kotlin-wasm-target-in-new-beta-a-new-approach-to-frontend-development/

https://seb.deleuze.fr/the-huge-potential-of-kotlin-wasm/

https://kotlinlang.org/docs/whatsnew-eap.html?utm_campaign=1.8.20-Beta&utm_medium=social&utm_source=twitter#leave-your-feedback-on-kotlin-wasm

推薦閱讀:

一個架構師在 2023 年需要掌握哪些“必殺技”?

本文轉載來源:

https://www.infoq.cn/news/WBIxUbWPE4OhI7Q4wtS2