TL;DR: 查看 Tuono 以获得类似框架的体验,它允许您在多线程 Rust 服务器上运行 React。您可以在下面找到更多详细信息。
在此处访问完整的项目。
在这个例子中,我们将使用 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",
在此示例中,我们将使用 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中文网其他相关文章!