本頁由機器翻譯,可能有錯誤。 閱讀英文原文

文件

平台概覽

NSH 可在手機、桌面與網頁上執行:iOS、Android、macOS、Windows、Linux、GPUI 與網頁。每個平台各有自己的後端,使用該平台原生的 UI 繪製,因此 App 在 iPhone 上是 UIKit 檢視,在 Mac 上是 AppKit 檢視,在 Linux 上是 GTK 4 元件,在 GPUI App 中是 GPUI 元素,在瀏覽器中則是 HTML,並採用該平台的文字、輸入、無障礙與深色模式。後端以上的部分全部共用:reactive graph、renderer、Taffy layout、元件與原生模組在各處都是相同的 Rust 程式碼,因此一個 App 可在所有平台上執行。以 Rust 撰寫的 App 就是這些程式碼加上你的 crate,不含 JavaScript VM;TSX App 則在其上以 QuickJS 執行模組(以 Rust 開發)。

在每個平台上,App 都以相同的兩種方式使用:打包成該平台可安裝的 App(nsh package),或嵌入你自己的原生 App,無論宿主連結的是 Rust root,還是在執行階段載入 TSX。開發時使用 nsh run(Rust 的修改會重新建置並重新啟動 App,TSX 的修改則是熱更新)。

#一覽

平台後端;文字執行環境開發打包
iOSUIKit;CoreTextiOS 15.0+,實機與模擬器nsh run --target ios.app(模擬器),已簽署的 .ipa
AndroidAndroid views;StaticLayoutAndroid 9 (API 28)+,arm64-v8a、armeabi-v7a 與 x86_64nsh run --target android已簽署的 .apk
macOSAppKit 與 Core Animation;CoreTextmacOS 14+nsh run --target macosad hoc 簽署的 .app
Windows以 Direct2D 繪製的 Win32 視窗;DirectWriteWindows 10 1809+、Windows 11nsh run(Windows 上的預設)一個目錄與一個 .zip
LinuxGTK 4 元件;PangoGTK 4.14+nsh run(Linux 上的預設)一個目錄與一個 .tar.gz
GPUIGPUI;GPUI 的文字系統macOS、Windows、Linux (Vulkan)在你的 GPUI App 中;TSX 也可使用 nsh run --target gpui內含於嵌入它的 GPUI App
WebHTML 與 CSS;瀏覽器的字型現代瀏覽器,桌面與手機nsh run --target web靜態網站
  • GPUI 在 macOS、Windows 與 Linux 上同樣以 GPUI(姊妹專案 GPUI Kit 的框架)繪製 App:它是嵌入 GPUI 與 GPUI Kit App 的後端,這些 App 會將 AppView 放進自己的元素樹。獨立桌面 App 則以各作業系統自己的後端(AppKit、Win32、GTK 4)執行與打包。
  • Web 將 App 以 HTML 渲染在瀏覽器頁面中:nsh package --target web 會發佈可用於任何網頁伺服器或 CDN 的靜態網站,Rust App 的引擎與 crate 會編譯為 WebAssembly,而你自己的頁面可用 createPlayer 或 iframe 嵌入 App。本站的即時範例與 playground 也是以它執行。
  • Mac Catalyst 在 Mac 上以 iPhone 大小(390×844)的視窗執行 iOS 後端,供開發使用。以 --target catalyst 選取它,即可查看 App 在手機上的樣子。

#開發與打包

在你未提供 --target 時,nsh run 會選擇本機自己的平台:macOS 上為 AppKit,Linux 上為 GTK 視窗,Windows 上為 Win32 視窗。手機需從電腦連接:iOS 需在裝有 Xcode 的 Mac 上,Android 則可在裝有 Android SDK 的 macOS、Linux 或 Windows 上(安裝)。

Rust App(其 nsh.json 指定 "root" 元件)從其目錄執行與打包:nsh 會為目標平台建置 App 專屬的 runner,內含你的 crate,且不含 QuickJS。TSX App 則需指定其入口:

# A Rust app, from its directory
nsh run --target macos             # or ios, android, windows, linux, web, catalyst
nsh package --target macos         # or ios, ios-simulator, android, windows, linux, web

# A TSX app
nsh run App.tsx --target macos     # or ios, android, windows, linux, gpui, web, catalyst
nsh package App.tsx --target macos

每個桌面作業系統都以自己的後端打包 App,且須在其執行的機器上建置:Mac App 在 Mac 上打包,Windows App 在 Windows 上打包,Linux App 在 Linux 上打包。打包涵蓋每個目標的輸出、簽署與圖示。

#嵌入原生 App

平台宿主檢視執行發佈形式宿主語言
macOSAppView(一個 NSView)Rust root、TSX bundlensh-platform-macos crateRust
WindowsAppView(一個子視窗)Rust root、TSX bundlensh-platform-windows crateRust
LinuxAppView(一個 GTK 元件)Rust root、TSX bundlensh-platform-linux crateRust
GPUI(macOS、Windows、Linux)AppView(一個 GPUI 檢視)Rust root、TSX bundle、已簽署的套件nsh-platform-gpui crateRust
iOSAppView(一個 UIView)Rust root、TSX bundlensh-platform-ios crateRust
iOSNshAppView(一個 UIView)TSX bundle、已簽署的套件NativeShell.xcframeworkSwift
AndroidNshView(一個 FrameLayout)TSX bundle、已簽署的套件nsh.aarJava 或 Kotlin
WebcreatePlayer(一個頁面元素)或 iframeTSX bundle;Rust App 則是其發佈的網站來自 nsh package --target web 的執行階段檔案JavaScript 或 HTML

Rust 宿主以 AppSource::Rust 或 App::Rust 掛載 Rust root(Root::of::<App>()),並以 set_ui_sets 為其引擎提供 App 的 UI 集合,因此它載入的 TSX 可匯入 App 自己的元件與模組。每個檢視是一個引擎,一個 App 可顯示多個。宿主在每個平台上都可註冊自己的原生檢視供 App 使用(原生元件)。

#為所有平台撰寫

App 的大部分內容不需要檢查平台:元素、樣式、版面與模組在各處的行為都相同。在平台有差異之處,NSH 為差異提供了單一的處理位置(平台專屬程式碼):

  • 環境會告訴你 App 在哪裡執行:在 Rust 中是 os()、idiom() 與 is_desktop()(nsh_core::prelude),在 TSX 中是來自 nsh 的 platform.os、platform.idiom、platform.desktop 與 platform.select。作業系統為 iOS、Android、macOS、Windows、Linux 或網頁。
  • 僅限特定平台的 props 在 TSX 中放入 ios={{…}}、android={{…}}、web={{…}} 或 desktop={{…}}(desktop:macOS、Windows、Linux 與桌面瀏覽器)。
  • 輸入隨平台而異。 手機使用觸控與軟體鍵盤;桌面使用滑鼠、觸控板與鍵盤。

App 的元件以 NSH 的 primitives 繪製,因此既能在桌面上執行,也能在手機上執行,且兩者外觀一致。桌面版面由 primitives 組成(view、text、scroll、virtual_list 等;TSX 中為 View、Text、Scroll、List 等),再加上對桌面的檢查,就像 gallery 的桌面版面那樣:

use nsh_core::prelude::*;

#[component]
pub fn Shell() -> impl IntoElement {
    // macOS, Windows, Linux and desktop browsers get a sidebar; phones get tabs.
    view()
        .flex_1()
        .child(if is_desktop() { sidebar_layout() } else { tab_layout() })
}

fn sidebar_layout() -> AnyElement {
    view().flex_1().flex_row().into_element()
}

fn tab_layout() -> AnyElement {
    view().flex_1().flex_col().into_element()
}

各後端都列出了它以自己方式處理的項目:macOS、Windows、Linux、GPUI。

#另請參閱

  • 開始使用:第一個 App,在各平台上執行。
  • 以 Rust 開發:以 Rust 撰寫的 App,以及 Rust 搭配 TSX。
  • 安裝:各平台所需的工具。
  • 架構:哪些部分共用,以及各後端負責什麼。