在前幾天的文章中,我們已經成功地使用 Tauri 建立起桌面和手機應用程式的基本框架。我們看到了由前端網頁技術(HTML、CSS、JavaScript)構成的用戶介面,以及背後由 Rust 驅動的核心。然而,到目前為止,這兩者之間就像是兩個獨立的世界,前端是前端,後端是後端,它們還無法有效地溝通。
如果我們的應用程式只能顯示靜態網頁,那它與一個普通的網站就沒有太大區別了。Tauri 的真正威力在於,它能讓你的網頁前端擁有存取原生系統功能的能力,例如讀寫檔案、顯示系統通知、操作硬體等。而實現這一切的關鍵,就是我們今天要探討的主題:IPC (Inter-Process Communication),也就是跨行程通訊。
在 Tauri 的架構中,你的應用程式實際上是由至少兩個不同的行程所組成:
這兩個行程在記憶體空間上是完全隔離的,這也是 Tauri 安全模型的重要一環。WebView 無法直接存取檔案系統或執行敏感操作,它必須「請求」Rust 核心行程來代為執行。IPC 就是它們之間用來傳遞這些「請求」和「回應」的標準化通道。
所以,每當你在前端呼叫一個 Tauri 的 API 時,背後都是透過 IPC 向 Rust 核心發送一條序列化後的訊息。Rust 核心接收到訊息後,執行對應的原生功能,再將結果透過 IPC 回傳給前端。
為了滿足不同的通訊需求,Tauri 設計了兩種主要的 IPC 方式:
Command (命令):這是一種前端主動發起的通訊模式。當使用者在介面上點擊一個按鈕,需要後端執行某個任務時(例如儲存檔案),前端就會發送一個 Command 請求給後端。後端接收到請求後,執行對應的 Rust 函式,並可以將執行結果回傳給前端。這是一種典型的「請求-回應」模型 ( Request-Response Model)。
Event (事件):這是一種後端主動發起的通訊模式。在某些場景下,後端需要主動通知前端某個狀態的變化,而不需要等待前端的請求。例如,一個長時間的下載任務,後端可以持續地觸發進度更新的 Event 給前端,讓介面上的進度條即時更新。這是一種「發布-訂閱」模型 (Publish-Subscribe Model)。
如果你曾經使用過 Electron.js,你會發現 Tauri 的 IPC 設計有著相似的概念。Electron 同樣採用了多行程架構:
在 IPC 通訊機制上,兩者都提供了類似的雙向通訊能力:
Electron 的 IPC:
ipcMain.handle()
和 ipcRenderer.invoke()
進行請求-回應通訊ipcMain.on()
和 ipcRenderer.send()
進行事件式通訊Tauri 的 IPC:
兩者在 IPC 設計理念上十分相近,都採用了事件驅動的訊息傳遞模式,讓前後端能夠靈活地進行雙向通訊。
今天我們深入了解了 Tauri 前後端溝通的核心機制——IPC。IPC 是連接使用者介面和強大原生功能的重要橋樑,有了 IPC,應用程式就能突破瀏覽器的安全限制,實現真正的桌面應用功能。
明天我們會深入探討 IPC 最常用的方式:Command
,看看怎麼定義各種不同的後端函式、處理各種參數和回傳值。