跳至主要内容

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 箱管理窗口、Webview 和对操作系统的调用。此项目由 Cargo 管理,Cargo 是 Rust 的官方包管理器和通用构建工具。

我们的 Tauri CLI 在底层使用 Cargo,因此你很少需要直接与它交互。Cargo 还有更多有用的功能,这些功能未通过我们的 CLI 暴露,例如测试、linting 和格式化,因此请参阅其 官方文档 了解更多信息。

安装 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. 你的 Web 资产 (HTML/CSS/JS) 相对于将要创建的 <current dir>/src-tauri/tauri.conf.json 文件位于何处?
    这是 Tauri 在为 生产 构建时将从其加载前端资产的路径。
    为此值使用 ../out

  4. 您的开发服务器的 URL 是什么?
    这可以是 Tauri 在开发期间将加载的 URL 或文件路径。
    为此值使用 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 函数是入口点,也是程序运行时调用的第一个函数。

  • 图标
    您可能希望为您的应用程序添加一个时髦的图标!为了让您快速上手,我们包含了一组默认图标。在发布您的应用程序之前,您应该将它们换掉。在 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 进程间通信 指南。