跳至主要內容

Next.js

本指南將引導您使用 React 框架 Next.js 建立您的第一個 Tauri 應用程式。

資訊

在我們繼續之前,請確定您已完成 先決條件,以建立一個可用的開發環境。

Tauri 是使用任何前端框架和 Rust 核心來建置桌面應用程式的框架。每個應用程式包含兩個部分

  1. 建立視窗並對這些視窗公開原生功能的 Rust 二進位檔
  2. 您選擇用於在視窗內產生使用者介面的前端

在以下內容中,我們將先建立前端架構、設定 Rust 專案,最後展示如何在這兩者之間進行通訊。

以下是我們將建置內容的預覽

Application Preview Application Preview

建立前端

Next.js 是 React 框架,同時具備伺服器端渲染 (SSR) 和靜態網站產生 (SSG) 功能。為了讓 Next.js 與 Tauri 搭配使用,我們將使用 SSG 模式,因為它只會產生靜態檔案,這些檔案可以包含在最終二進位檔中。

Next.js 附帶一個類似於 create-tauri-app 的架構實用程式,可以快速從許多預定義範本中設定新的專案。對於本指南,我們將對所有問題使用建議的預設值,包括 TypeScript 支援和 v13.4 中穩定的新 App Router 功能。如果您使用舊的 pages/ 目錄代替或在 app/ 目錄之上,您仍然需要按照 Next.js 靜態匯出 部分中所述變更設定檔,但您使用 Tauri 特定 JS API 的方式將與以下所述不同。

npx create-next-app@latest --use-npm
  1. 專案名稱
    這將是您的專案名稱。它對應於此實用程式將建立的資料夾名稱,但對您的應用程式沒有其他影響。您可以在此處使用任何您想要的任何名稱。

如果您使用 Typescript,您可能想要排除 src-tauri 目錄,以防止 Next.js/TypeScript 掃描它。您的 tsconfig.json 檔案應該已經包含一個 "exclude" 區段,您可以在其中新增它

tsconfig.json
  "exclude": [
"node_modules",
"src-tauri"
]

Next.js 靜態匯出

由於 Tauri 沒有 Node.js 執行時期,您必須將 Next.js 設定為 SSG/SPA 模式。這通常會導致更快的頁面載入速度,但也有一些需要注意的注意事項,因此我們建議仔細閱讀 Next.js 關於 靜態匯出 的官方文件。

這些文件還顯示了一個必要的設定檔變更,我們將始終必須為 Tauri + Next.js 應用程式變更。為此,請編輯專案根目錄中的 next.config.js 檔案,並新增下列內容

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
}

module.exports = nextConfig

這將變更 next build 的行為,以產生一個 out/ 資料夾,其中包含應用程式的 HTML/CSS/JS 資源,而不是將它們寫入特定於 Next.js 執行時期的 .next/ 目錄。

還有更多可能的組態選項,因此請務必閱讀上文提到的 靜態輸出 文件,並根據專案需求調整組態檔。

建立 Rust 專案

每個 Tauri 應用程式的核心都是一個 Rust 二進位檔,它透過稱為 tauri 的 Rust crate 來管理視窗、網頁檢視和對作業系統的呼叫。這個專案是由 Rust 的官方套件管理員和通用建置工具 Cargo 管理的。

我們的 Tauri CLI 在幕後使用 Cargo,因此您很少需要直接與它互動。Cargo 有更多未透過我們的 CLI 公開的有用功能,例如測試、程式碼檢查和格式化,因此請參閱他們的 官方文件 以取得更多資訊。

安裝 Tauri CLI

如果您尚未安裝 Tauri CLI,可以使用以下命令之一進行安裝。不確定要使用哪一個嗎?請查看 常見問題解答條目

npm install --save-dev @tauri-apps/cli
為了讓 npm 正確偵測 Tauri,您需要將它新增到 package.json 檔案的「scripts」區段
package.json
"scripts": {
"tauri": "tauri"
}

若要建立預先組態為使用 Tauri 的最小 Rust 專案,請開啟終端機並執行以下命令

npm run tauri init

它會引導您完成一系列問題

  1. 您的應用程式名稱為何?
    這將會是您最終套件的名稱,以及作業系統會如何稱呼您的應用程式。您可以在這裡使用任何您想要的應用程式名稱。

  2. 視窗標題應該是什麼?
    這將會是預設主視窗的標題。您可以在這裡使用任何您想要的標題。

  3. 您的網頁資源(HTML/CSS/JS)相對於將建立的 <current dir>/src-tauri/tauri.conf.json 檔案位於何處?
    這是 Tauri 在為生產環境建置時,將會從中載入您的前端資源的路徑。
    請使用 ../out 作為此值。

  4. 您的開發伺服器網址為何?
    這可以是 URL 或檔案路徑,Tauri 將在開發期間載入。
    請使用 http://localhost:3000 作為此值。

  5. 您的前端開發指令為何?
    這是用來啟動您的前端開發伺服器的指令。
    請使用 npm run dev 作為此值(請務必調整為使用您選擇的套件管理員)。

  6. 您的前端建置指令為何?
    這是用來建置您的前端檔案的指令。
    請使用 npm run build 作為此值(請務必調整為使用您選擇的套件管理員)。
資訊

如果您熟悉 Rust,您會注意到 tauri init 的外觀和運作方式與 cargo init 非常相似。如果您偏好完全手動設定,您可以直接使用 cargo init 並加入必要的 Tauri 相依性套件。

tauri init 指令會產生一個名為 src-tauri 的資料夾。Tauri 應用程式會將所有核心相關檔案放置到此資料夾中,這是一個慣例。讓我們快速瀏覽此資料夾的內容

  • Cargo.toml
    Cargo 的清單檔案。您可以宣告應用程式所依賴的 Rust 板條箱、應用程式的元資料,以及更多內容。有關完整參考,請參閱 Cargo 的清單格式

  • tauri.conf.json
    這個檔案讓您可以設定和自訂 Tauri 應用程式的各個面向,從應用程式的名稱到允許的 API 清單。請參閱 Tauri 的 API 設定,以取得支援選項的完整清單和每個選項的深入說明。

  • src/main.rs
    這是 Rust 程式碼的進入點,也是我們引導進入 Tauri 的地方。您會在其中找到兩個區段

    src/main.rs
     #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

    fn main() {
    tauri::Builder::default()
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
    }

    cfg! 巨集 開始的那一行只有一個目的:停用命令提示字元視窗,如果在 Windows 上執行已打包的應用程式,該視窗通常會彈出。如果您使用的是 Windows,請嘗試將它註解掉,看看會發生什麼事。

    main 函式是進入點,也是程式碼執行時第一個被呼叫的函式。

  • icons
    您很可能想要為應用程式設定一個時髦的圖示!為了讓您快速上手,我們包含了一組預設圖示。在發佈應用程式之前,您應該將這些圖示換掉。在 Tauri 的 圖示功能指南 中,進一步了解各種圖示格式。

現在我們已經建立好前端架構並初始化 Rust 專案,您幾乎可以執行應用程式了。您的 tauri.conf.json 檔案應該類似於以下內容

src-tauri/tauri.conf.json
{
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:3000",
"distDir": "../out"
},

這樣就完成了!現在您可以在終端機中執行以下指令,以開始應用程式的開發建置

npm run tauri dev

Application Window Application Window

呼叫指令

Tauri 讓您可以透過原生功能來增強您的前端。我們稱這些為指令,基本上是您可以從前端 JavaScript 呼叫的 Rust 函式。這讓您可以使用效能更高的 Rust 程式碼來處理繁重的處理或呼叫作業系統。

讓我們來做一個簡單的範例

src-tauri/src/main.rs
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}

指令就像任何一般的 Rust 函式,但額外加上 #[tauri::command] 屬性巨集,讓您的函式可以與 JavaScript 環境溝通。

最後,我們也需要告訴 Tauri 我們新建立的指令,以便它可以適當地路由呼叫。這會透過結合 .invoke_handler() 函式和您可以在下方看到的 generate_handler![] 巨集來完成

src-tauri/src/main.rs
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

現在您可以從前端呼叫您的指令了!

要呼叫我們新建立的指令,我們將使用 @tauri-apps/api JavaScript 函式庫。它提供對核心功能的存取,例如視窗操作、檔案系統等,並透過方便的 JavaScript 抽象化來實現。您可以使用您最喜歡的 JavaScript 套件管理員來安裝它

npm install @tauri-apps/api

需要注意的一件重要事情是,Tauri 的所有 JS API 都需要存取瀏覽器專屬 API,這表示它們只能用於用戶端元件。如果您不需要伺服器元件,您可以在 app/page.tsx 檔案的最上方加入 'use client',不過在本指南中,我們將建立一個獨立的元件,這樣我們就不必轉換整個應用程式。

app/greet.tsx
'use client'

import { useEffect, useState } from 'react';
import { invoke } from '@tauri-apps/api/tauri'

export default function Greet() {
const [greeting, setGreeting] = useState('');

useEffect(() => {
invoke<string>('greet', { name: 'Next.js' })
.then(result => setGreeting(result))
.catch(console.error)
}, [])

// Necessary because we will have to use Greet as a component later.
return <div>{greeting}</div>;
}

現在我們將在 app/page.tsx 中的預設 Home 元件中使用這個元件。請注意,它必須在實際的元件樹中,只要父元件(在本例中為 Home 元件)是伺服器元件,它就不能是簡單的函式呼叫。

app/page.tsx
// ...
import Greet from './greet'

export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<Greet />
...
</main>
)
}
提示

如果您想了解有關 Rust 和 JavaScript 之間通訊的更多資訊,請閱讀 Tauri 跨程序通訊指南。