跳到主要内容

Next.js

本指南将引导您使用 React 框架 Next.js 创建您的第一款 Tauri 应用程序。

信息

Before we continue, make sure you have completed the prerequisites to have a working development environment.

Tauri 由一个可搭配任何前端来构建桌面应用的框架和 Rust 核心构成。 每个应用均由两个部分组成:

  1. 创建窗口并向其提供原生功能支持的 Rust 二进制文件
  2. 由您选择的前端框架,用于编写窗口内的用户界面

接下来,我们会先搭建好前端框架,然后设置一个Rust工程,最后向你展示这两者之间如何通信。

这是我们将要构建的内容的预览:

应用预览 应用预览

创建前端

Next.js 是一款支持服务端渲染 (SSR) 和静态网站生成 (SSG) 的 React 框架。 由于 Tauri 仅能接受 Next.js 所生成的静态文件,我们将使用 Next.js 的静态网站生成模式。

Next.js comes with a scaffolding utility similar to create-tauri-app that can quickly setup a new project from many pre-defined templates. For this guide, we will use the TypeScript template to create a simple project.

npx create-next-app@latest --use-npm --typescript
  1. Project name
    This will be the name of your project. It corresponds to the name of the folder this utility will create but has otherwise no effect on your app. 您可以在此处填写任何您想要的名称。

  2. Experimental app/ directory
    Next.js will ask you if you want to try the new and experimental app/ directory. You must select No because it does not yet support the next export command.

在启动或构建前端时,Next.js 将在项目根目录中寻找名为 next.config.js 的配置文件。 我们想要自定义此文件以获得与 Tauri的最佳兼容性。

用以下内容更新文件:

next.config.js
/** @type {import('next').NextConfig} */

const nextConfig = {
reactStrictMode: true,
// Note: This feature is required to use NextJS Image in SSG mode.
// 请参见 https://nextjs.org/docs/messages/export-image-api 来了解不同的解决方法。
images: {
unoptimized: true,
},
}

module.exports = nextConfig

要能够在生产中构建,我们必须在 package.json 中添加一个 next export 命令。 这将在 out 文件夹中生成一个静态的 HTML/JavaScript 版本的 Next.js。 还要将 tauri 命令添加到 package.json 中。

您的 package.json 看起来像这样:

package.json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"export": "next export",
"start": "next start",
"tauri": "tauri",
"lint": "next lint"
},

Next.js 中使用 SSG 模式

使用 SSG 模式的优势在于预渲染 React 代码并生成在静态的 HTML/JavaScript 中。 这意味着页面能够更快加载。 React 不必在客户端渲染 HTML,但需要时会在第一次加载中对它进行混合。 The "downside" is that we cannot use getServerSideProps or use any type of "data fetching" for rendering our page for a request.

提示

您可以使用 getStaticProps 在构建时间生成 HTML/JavaScript 页面。 因为它是在 Node.js 环境中执行的,调用 Tauri API 不会起作用。 您可以在 官方文档 中了解更多关于 Next.js SSG 的信息。

创建 Rust 项目

每款 Tauri 应用的核心都是由一个管理窗口的 Rust 二进制文件、WebView 和进行系统调用的 tauri Rust 包构成。 此项目使用官方的软件包管理器及 Rust 通用构建工具 Cargo 来管理。

我们的 Tauri CLI 工具会在底层自动调用 Cargo,所以您大部分情况下无需和其交互。 Cargo 有诸多我们的 CLI 工具所未提供的有用功能,包括测试、分析及格式化工具。请参阅其官方文档来了解更多。

安装 Tauri CLI

如果你还没有安装Tauri CLI,你可以使用下面的一个命令进行安装。 不确定该用哪个? 请参阅常见问题

npm install --save-dev @tauri-apps/cli
For npm to detect Tauri correctly you need to add it to the "scripts" section in your package.json file:
package.json
"scripts": {
"tauri": "tauri"
}

要搭建一个使用 Tauri 的简单 Rust 项目,请打开终端并运行如下命令:

npm run tauri init

它会向您询问几个问题:

  1. 您应用的名字是什么?
    这将会是您打包后和操作系统会调用的应用名称。 您可以在此处填写任何您想要的名称。

  2. 窗口标题叫什么?
    这将会是您主窗口的默认标题。 您可以在此处填写任何您想要的名称。

  3. 前端页面资源 (HTML/CSS/JS) 相对于 <current dir>/src-tauri/tauri.conf.json 文件将被创建的位置?
    这是 production环境时tauri加载web前端资源的目录.
    Use ../out for this value.

  4. 开发环境时的加载路径?
    可以是一个网络地址也可以是一个文件路径 development.
    Use http://localhost:3000 for this value.

  5. 你将使用什么命令来开发前端页面?
    这是启动前端开发服务器的命令。
    Use npm run dev for this value.

  6. 你将使用什么命令来构建前端页面?
    这是构建前端文件的命令。
信息

若您已熟悉 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(
    all(not(debug_assertions), target_os = "windows"),
    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 && npm run export",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:3000",
"distDir": "../out"
},

就是这样! 现在您可以在您的终端中运行接下来的命令来开始您的应用程序的开发构建:

npm run tauri dev

应用窗口 应用窗口

调用指令

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

With the library installed, you can modify your pages/index.tsx file to call the Command:

pages/index.tsx
import { invoke } from '@tauri-apps/api/tauri'

// Note: When working with Next.js in development you have 2 execution contexts:
// - The server (nodejs), where Tauri cannot be reached, because the current context is inside of nodejs.
// - The client (webview), where it is possible to interact with the Tauri rust backend.
// To check if we are currently executing in the client context, we can check the type of the window object;
const isClient = typeof window !== 'undefined'

// Now we can call our Command!
// 在应用窗口中右键,打开开发者工具
// You will see "Hello, World!" printed in the console.
isClient &&
invoke('greet', { name: 'World' }).then(console.log).catch(console.error)

一个更好的方法是在 componentDidMountuseEffect 中使用 Tauri。 这样 Tauri 通过 Next.js 就仅在客户端环境中运行。

为了使它更干净,我们应该像这样重写:

pages/index.tsx
import { invoke } from "@tauri-apps/api/tauri"

const Home: NextPage = () => {
useEffect(() => {
invoke('greet', { name: 'World' })
.then(console.log)
.catch(console.error)
}, []);
提示

若您想要了解更多有关 Rust 和 JavaScript 之间通信的信息,请参阅 Tauri 进程间通信指南。