首页 >web前端 >js教程 >使用 Rust 进行服务器端渲染 React 的分步指南

使用 Rust 进行服务器端渲染 React 的分步指南

DDD
DDD原创
2024-12-04 02:18:10687浏览

Step-by-Step Guide to Server-Side Render React with Rust

TL;DR: 查看 Tuono 以获得类似框架的体验,它允许您在多线程 Rust 服务器上运行 React。您可以在下面找到更多详细信息。

在此处访问完整的项目。

要求

  • Node.js(仅用于使用 vite 构建项目)
  • NPM(节点包管理器)
  • Rustup(Rust 语言工具链)
  • Cargo(Rust 包管理器)

入门

在这个例子中,我们将使用 Vite.js 来建立项目并编译 React 源代码。

npm create vite@latest react-rust -- --template react-ts

初始化的项目专为客户端应用程序而设计。在下一节中,我们将探讨使其适应全栈捆绑的必要条件。

反应设置

React 需要针对不同环境定制的两个不同的构建:

  • 客户端构建
  • 服务器端构建

这两个输出有什么区别?

客户端构建包含所有水合逻辑,使 React 能够与服务器生成的 HTML 无缝连接。相比之下,服务器构建是一个更精简的版本,仅专注于根据从服务器接收到的 props 渲染 HTML。

现在,让我们创建一个名为 ./src/server.tsx 的新文件,它将作为服务器构建的入口点,并插入以下代码:

import "fast-text-encoding"; // Mandatory for React18
import { renderToString } from "react-dom/server";
import App from "./App";

export const Server = () => {
    const app = renderToString(<App />);
    return `<!doctype html>
<html>
    <head>
        <title>React + Rust = ❤️</title>
        <script type="module" crossorigin src="/index.js"></script>
    </head>
    <body>
        <div>



<blockquote>
<p>If you're working with React 18 or a newer version, it's essential to run npm install fast-text-encoding. This step is necessary because the Rust server lacks the Node.js objects and functions and the Web APIs. As a result, we need to provide a polyfill for TextEncoder, which is required by react-dom/server (in fact it is declared beforehand).</p>
</blockquote>

<p>We need to modify the vite.config.ts file to include the two outputs:<br>
</p>

<pre class="brush:php;toolbar:false">import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: "iife",
        dir: "dist/",
      },
    },
  },
  ssr: {
    target: "webworker",
    noExternal: true,
  },
  plugins: [react()],
});

接下来,我们应该在 package.json 文件中添加一个新脚本。

-- "build": "tsc && vite build",
++ "build": "tsc && vite build && vite build --ssr src/server.tsx",

准备 Rust 服务器

在此示例中,我们将使用 axum,一个在 tokio 之上运行的 Web 框架。

首先,让我们通过在主目录中创建 Cargo.toml 文件来设置 Rust 项目,其中包含以下详细信息:

[package]
name = "react-rust-ssr-example"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "ssr"
path = "src/server/server.rs"

[dependencies]
ssr_rs="0.7.0"
tokio = { version = "1", features = ["full"] }
axum = "0.7.4"
tower-http = {version = "0.6.0", features = ["fs"]}

这是 Rust 清单 - 与 JavaScript package.json 文件非常相似。

接下来,我们将设置一个名为 src/server/server.rs 的文件,它将作为启动 Rust 服务器的入口点。

use axum::{response::Html, routing::get, Router};
use ssr_rs::Ssr;
use std::cell::RefCell;
use std::fs::read_to_string;
use std::path::Path;
use tower_http::services::ServeDir;

thread_local! {
    static SSR: RefCell<Ssr<'static, 'static>> = RefCell::new(
            Ssr::from(
                read_to_string(Path::new("./dist/server.js").to_str().unwrap()).unwrap(),
                ""
                ).unwrap()
            )
}

#[tokio::main]
async fn main() {
    Ssr::create_platform();
    // build our application with a single route
    let app = Router::new()
        .route("/", get(root))
        .fallback_service(ServeDir::new("dist"));

    // run our app with hyper, listening globally on port 3000
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}

async fn root() -> Html<String> {
    let result = SSR.with(|ssr| ssr.borrow_mut().render_to_string(None));
    Html(result.unwrap())
}

这就是魔法展现的地方。在程序开始时,我们首先使用 Ssr::create_platform(); 初始化 JavaScript V8 引擎;接下来,我们使用 thread_local! 在每个线程中创建一个 V8 上下文。最后,我们使用 SSR.with(|ssr| ssr.borrow_mut().render_to_string(None)); 渲染 HTML并在请求路由 http://localhost:3000/ 时发送给客户端。

运行服务器

要启动服务器,只需使用 Vite 编译资产,然后启动 Rust 服务器即可。

npm run build && cargo run

? 您正在使用 Rust 服务器运行全栈 React 应用程序。最后,React 在多线程服务器中运行(您可以在此处找到一些基准测试)。

最后的话

使用 Node.js 管理全栈 React 应用程序并不容易,已经有很多工具被加班构建来支持它,而正如您所看到的,使用 Rust 则更加困难。

Tuono 是一个实验性全栈框架,旨在简化高性能 Rust 应用程序的开发,重点关注可用性和速度。

以上是使用 Rust 进行服务器端渲染 React 的分步指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn