Passa al contenuto principale

Next.js

This guide will walk you through creating your first Tauri app using the React framework Next.js.

info

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

Tauri è un framework per costruire applicazioni desktop con qualsiasi framework Front-end e un nucleo in Rust. Ogni app consiste di due parti:

  1. Un binario Rust che crea le finestre ed espone le funzionalità native a quelle finestre
  2. Un Frontend di tua scelta che produce l'Interfaccia Utente all'interno della finestra

Di seguito, strutturiamo prima il Frontend, poi impostiamo il progetto Rust ed infine ti mostriamo come farli comunicare tra di loro.

Ecco un'anteprima di quello che costruiremo:

Anteprima Dell'Applicazione Anteprima Dell'Applicazione

Crea il Frontend

Next.js is a React Framework that comes with both Server-Side Rendering (SSR) and Static-Site Generation (SSG) capabilities. To make Next.js work with Tauri we are going to use the SSG mode since it generates only static files that can be included in the final binary.

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. È possibile utilizzare il nome che si desidera.

  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.

When starting or building the frontend, Next.js will look for a config file named next.config.js inside the project root. Vogliamo personalizzare questo file per ottenere la migliore compatibilità con Tauri.

Aggiorna il file con il seguente contenuto:

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

const nextConfig = {
reactStrictMode: true,
// Note: This feature is required to use NextJS Image in SSG mode.
// See https://nextjs.org/docs/messages/export-image-api for different workarounds.
images: {
unoptimized: true,
},
}

module.exports = nextConfig

To be able to build in production we must add a next export command in package.json. This will produce a static HTML/JavaScript version of your Next.js application in the out folder. We'll also add the tauri command to package.json.

Your package.json should look like this:

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

Next.js in SSG mode

The "benefit" of using SSG mode is pre-rendered React code in static HTML/JavaScript. This means your page can load faster. React doesn't have to render the HTML on the client-side but will hydrate it on the first load if needed. The "downside" is that we cannot use getServerSideProps or use any type of "data fetching" for rendering our page for a request.

consiglio

You can use getStaticProps to generate HTML/JavaScript pages at build time. Since it is executed in the Node.js context, calling the Tauri api won't work. You can learn more about Next.js SSG in the official documentation.

Crea il progetto Rust

At the heart of every Tauri app is a Rust binary that manages windows, the webview, and calls to the operating system through a Rust crate called tauri. Questo progetto è gestito da Cargo, il gestore ufficiale di pacchetti e lo strumento di costruzione tuttofare per Rust.

Tauri CLI utilizza Cargo dietro le quinte quindi raramente è necessario interagire con esso direttamente. Cargo ha molte caratteristiche utili che non sono esposte attraverso la CLI, come testing, linting, e formattazione, quindi invitiamo a riferirsi alla loro documentazione ufficiale per saperne di più.

Installa Tauri CLI

If you haven't installed the Tauri CLI yet you can do so with one of the below commands. Non sei sicuro quale usare? Dai un'occhiata alla voce FAQ.

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"
}

Per strutturare un progetto Rust minimale preconfigurato per utilizzare Tauri, apri un terminale ed esegui il seguente comando:

npm run tauri init

Vi guiderà attraverso una serie di domande:

  1. What is your app name?
    This will be the name of your final bundle and what the OS will call your app. È possibile utilizzare il nome che si desidera.

  2. What should the window title be?
    This will be the title of the default main window. You can use any title you want here.

  3. Where are your web assets (HTML/CSS/JS) located relative to the <current dir>/src-tauri/tauri.conf.json file that will be created?
    This is the path that Tauri will load your frontend assets from when building for production.
    Use ../out for this value.

  4. What is the URL of your dev server?
    This can be either a URL or a file path that Tauri will load during development.
    Use http://localhost:3000 for this value.

  5. What is your frontend dev command?
    This is the command used to start your frontend dev server.
    Use npm run dev for this value.

  6. What is your frontend build command?
    This is the command to build your frontend files.
    Use npm run build && npm run export for this value.
info

Se hai familiarità con Rust, noterai che tauri init sembra e funziona molto come cargo init. È possibile utilizzare cargo init e aggiungere le dipendenze Tauri necessarie se si preferisce una configurazione completamente manuale.

Il comando tauri init genera una cartella chiamata src-tauri. È una convenzione per le applicazioni Tauri dove inserire tutti i file correlati al nucleo in questa cartella. Attraversiamo rapidamente i contenuti della cartella:

  • Cargo.toml
    Cargo's manifest file. È possibile dichiarare crates Rust da cui la tua app dipende, metadati sulla tua app, e molto altro. Per il riferimento completo vedi Formato Manifesto di Cargo.

  • tauri.conf.json
    This file lets you configure and customize aspects of your Tauri application from the name of your app to the list of allowed APIs. Vedere Configurazione API di Tauri per l'elenco completo delle opzioni supportate e le spiegazioni approfondite per ciascuno.

  • src/main.rs
    This is the entry point to your Rust program and the place where we bootstrap into Tauri. Troverete due sezioni in esso:

    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");
    }

    La linea che inizia con la macro cfg! ha un solo scopo: disattiva la finestra del prompt dei comandi che normalmente apparirebbe su Windows se si eseguisse un app impacchettata. Se sei su Windows, prova a commentarlo e vedi cosa succede.

    La funzione main è il punto di entrata e la prima funzione che viene invocata quando il programma viene eseguito.

  • icons
    Chances are you want a snazzy icon for your app! Per farti andare velocemente, abbiamo incluso un set di icone predefinite. Dovresti cambiarli prima di pubblicare la tua applicazione. Scopri di più sui vari formati di icone nella guida delle icone di Tauri.

Now that we have scaffolded our frontend and initialized the Rust project you're almost ready to run your app. Your tauri.conf.json file should look something like this:

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

E questo è tutto! Ora puoi eseguire il seguente comando nel terminale per avviare una build di sviluppo della tua app:

npm run tauri dev

Finestra Dell&#39;Applicazione Finestra Dell&#39;Applicazione

Invoca Comandi

Tauri lets you enhance your frontend with native capabilities. Chiamiamo queste funzionalità Comandi, sono essenzialmente funzioni Rust che puoi chiamare dal tuo Frontend JavaScript. Questo ti consente di gestire elaborazioni pesanti o chiamate al SO tramite codice Rust più performante.

Facciamo un piccolo esempio:

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

Un Comando è come qualsiasi funzione Rust, con l'aggiunta dell'attributo macro #[tauri::command] che permette alla tua funzione di comunicare con il contesto JavaScript.

Infine, dobbiamo anche dire a Tauri del nostro nuovo Comando in modo che possa indirizzare le chiamate di conseguenza. Questo è fatto con la combinazione della funzione .invoke_handler() e della macro generate_handler![] che puoi vedere sotto:

src-tauri/src/main.rs
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("Errore nell'eseguire l'applicazione tauri");
}

Now you're ready to call your Command from the frontend!

To call our newly created command we will use the @tauri-apps/api JavaScript library. It provides access to core functionality such as window manipulation, the filesystem, and more through convenient JavaScript abstractions. È possibile installarlo utilizzando il gestore di pacchetti JavaScript preferito:

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!
// Right-click on the application background and open the developer tools.
// You will see "Hello, World!" printed in the console.
isClient &&
invoke('greet', { name: 'World' }).then(console.log).catch(console.error)

A better approach would be to use Tauri calls in componentDidMount or useEffect that are only run on the client-side by Next.js.

So to make it cleaner we should rewrite it like this:

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

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

If you want to know more about the communication between Rust and JavaScript, please read the Tauri Inter-Process Communication guide.