优秀的编程知识分享平台

网站首页 > 技术文章 正文

基于 Rust 和 React 新一代全栈 Web 框架 Tuono 强势来袭!

nanyue 2025-08-05 20:16:24 技术文章 2 ℃

家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

什么是 Tuono

Tuono 是一个 Web 全栈框架,用于构建 React 应用,使用 Rust 作为后端,并高度重视可用性和性能,意大利语中意为 “雷霆”,发音为 /2OhNo/。

如果开发者有 Next.js 使用经验,那么使用 Tuono 将会非常简单。其核心功能包括:

  • 原生 Typescript
  • 类似 Next.js 的路由
  • CSS/SCSS 模块
  • 服务器端渲染
  • 热模块刷新

Tuono 主要解决了以下两个限制:

  • 无需使用 JS 运行时(Node、Deno)即可启用 React 服务器端渲染项目
  • 使用 Rust 等通常比较难的语言简化 Web 开发

同时,Tuono API 尽可能地与 Next.js 保持一致,主要区别在于后端系统。Next.js 完全依赖于 Node/Deno/Bun,而 Tuono 无需任何中间运行时即可运行服务器,从而带来了显著的性能提升。

目前 Tuono 在 Github 通过 MIT 协议开源并非常活跃,短短时间内已经有接近 1k 的 star,是一个值得关注的前端开源项目。

如何使用 Tuono

首先需要安装相应的依赖:

cargo install tuono
tuono --version

Tuono 支持使用 tuono new CLI 命令从头开始创建新项目,开发者只需要输入下面命令:

tuono new my-first-tuono-app
cd my-first-tuono-app
npm install
tuono dev
// 开发
tuono build
// build 构建
cargo run --release
// 发布

下面是基于 Tuono 的一个服务器端路由示例:

// src/routes/pokemons/[pokemon].rs
use serde::{Deserialize, Serialize};
use reqwest::Client;
use tuono_lib::{Props, Request, Response};
const POKEMON_API: &str = "https://pokeapi.co/api/v2/pokemon";
#[derive(Debug, Serialize, Deserialize)]
struct Pokemon {
    name: String,
    id: u16,
    weight: u16,
    height: u16,
}
#[tuono_lib::handler]
async fn get_pokemon(req: Request, fetch: Client) -> Response {
    // The param `pokemon` is defined in the route filename [pokemon].rs
    let pokemon = req.params.get("pokemon").unwrap();
    return match fetch.get(format!("{POKEMON_API}/{pokemon}")).send().await {
        Ok(res) => {
            let data = res.json::<Pokemon>().await.unwrap();
            Response::Props(Props::new(data))
        }
        Err(_err) => Response::Props(Props::new("{}"))
    };
}

由于基于 React,使用 tuono 创建客户端页面也非常简单,例如:下面实例创建了
src/components/PokemonLink.tsx 组件:

// src/components/PokemonLink.tsx
import type {JSX} from 'react'
import {Link} from 'tuono'

interface PokemonLinkProps {
  id: number
  name: string
}
export default function PokemonLink({
  id,
  name,
}: PokemonLinkProps): JSX.Element {
  return (
    <Link href={`/pokemons/${name}`} id={id.toString()}>
      {name}
      <img
        src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${id}.png`}
        alt=""
      />
    </Link>
  )
}

tuono 还支持 SSR 等高级特性,假设页面需要预渲染频繁更新的数据(从本地文件读取)。开发者可以编写一个处理程序,读取 JSON 文件并将其传递给路由,如下所示:

// src/routes/about.rs
use tuono_lib::{Request, Response, Props};
use std::fs;

#[tuono_lib::handler]
async fn my_custom_ssr_page(req: Request) -> Response {
  let data = fs::read_to_string("my_data.json").expect("Failed to read json file");
  Response::Props(Props::new(data))
}

数据加载完成后,开发者就可以通过路由上的 data prop 访问。

更多关于 Tuono 的用法和示例可以参考文末资料,本文不再过多展开。

参考资料

https://github.com/tuono-labs/tuono

https://tuono.dev/documentation/rendering/server-side-rendering

Tags:

最近发表
标签列表