跳至主要内容

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 的行为,以生成包含应用程序的 HTML/CSS/JS 资源的 out/ 文件夹,而不是将它们写入特定于 Next.js 运行时的 .next/ 目录。

还有更多可能的配置选项,因此请确保阅读上面提到的 静态导出 文档,并根据项目的需要调整配置文件。

创建 Rust 项目

每个 Tauri 应用程序的核心都是一个 Rust 二进制文件,它通过名为 tauri 的 Rust crate 管理窗口、webview 和对操作系统的调用。此项目由 Cargo 管理,Cargo 是 Rust 的官方包管理器和通用构建工具。

我们的 Tauri CLI 在后台使用 Cargo,因此您很少需要直接与它交互。Cargo 还有许多通过我们的 CLI 未公开的更有用的功能,例如测试、代码检查和格式化,因此请参阅其 官方文档 以了解更多信息。

安装 Tauri CLI

如果您尚未安装 Tauri CLI,可以使用以下命令之一进行安装。不确定使用哪个?查看 常见问题解答条目

npm install --save-dev @tauri-apps/cli@">1.0.0"
为了让 npm 正确检测 Tauri,您需要将其添加到 package.json 文件中的 "scripts" 部分。
package.json
"scripts": {
"tauri": "tauri"
}

要搭建一个预先配置为使用 Tauri 的最小 Rust 项目,请打开终端并运行以下命令:

npm run tauri init

它将引导您完成一系列问题:

  1. 您的应用程序名称是什么?
    这将是您最终捆绑包的名称,也是操作系统将您的应用程序称为什么。您可以在此处使用任何您想要的名称。

  2. 窗口标题应是什么?
    这将是默认主窗口的标题。您可以在此处使用任何您想要的标题。

  3. 您的 Web 资源 (HTML/CSS/JS) 相对于将要创建的 <当前目录>/src-tauri/tauri.conf.json 文件位于哪个位置?
    这是 Tauri 在为 **生产环境** 构建时将从中加载前端资源的路径。
    为此值使用 ../out

  4. 您的开发服务器的 URL 是什么?
    这可以是 Tauri 在 开发期间将加载的 URL 或文件路径。.
    为此值使用 https://127.0.0.1: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 crate、关于您的应用程序的元数据等等。有关完整参考,请参阅 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 函数是入口点,也是程序运行时调用的第一个函数。

  • 图标
    您可能想要一个漂亮的应用程序图标!为了让您快速上手,我们包含了一组默认图标。您应该在发布应用程序之前更换这些图标。在 Tauri 的 图标特性指南 中了解有关各种图标格式的更多信息。

现在我们已经搭建了前端并初始化了 Rust 项目,您几乎可以运行您的应用程序了。您的 tauri.conf.json 文件应该如下所示:

src-tauri/tauri.conf.json
{
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "https://127.0.0.1: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@">1.0.0"

需要注意的一点是,所有 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 的 进程间通信 指南。