使用 TanStack Start 进行 SSR
在 Nitro 中使用 Vite 配合 TanStack Start 实现全栈 React。
server.ts
import handler, { createServerEntry } from "@tanstack/react-start/server-entry";
export default createServerEntry({
fetch(request) {
return handler.fetch(request);
},
});
使用 Nitro 设置 TanStack Start,获得包含服务端渲染、基于文件的路由和集成 API 路由的全栈 React 框架体验。
概述
将 Nitro Vite 插件添加到你的 Vite 配置中
使用 TanStack Start 的服务端处理程序创建服务端入口
使用默认组件配置路由
使用基于文件的路由定义路由和 API 端点
1. 配置 Vite
将 Nitro、React、TanStack Start 和 Tailwind 插件添加到你的 Vite 配置中:
vite.config.mjs
import { defineConfig } from "vite";
import { nitro } from "nitro/vite";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import viteReact from "@vitejs/plugin-react";
import viteTsConfigPaths from "vite-tsconfig-paths";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [
viteTsConfigPaths({ projects: ["./tsconfig.json"] }),
tanstackStart(),
viteReact(),
tailwindcss(),
nitro(),
],
environments: {
ssr: { build: { rollupOptions: { input: "./server.ts" } } },
},
});
tanstackStart() 插件提供了完整的 SSR 集成,并自动处理客户端入口。使用 viteTsConfigPaths() 来启用 tsconfig 中的路径别名,如 ~/。environments.ssr 选项指向服务端入口文件。
2. 创建服务端入口
创建一个使用 TanStack Start 处理程序的服务端入口:
server.ts
import handler, { createServerEntry } from "@tanstack/react-start/server-entry";
export default createServerEntry({
fetch(request) {
return handler.fetch(request);
},
});
TanStack Start 自动处理 SSR。createServerEntry 包装器与 Nitro 的服务端入口格式集成,handler.fetch 处理所有传入的请求。
3. 配置路由
创建一个包含默认错误和未找到组件的路由工厂函数:
src/router.tsx
import { createRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen.ts";
export function getRouter() {
const router = createRouter({
routeTree,
defaultPreload: "intent",
defaultErrorComponent: () => <div>Internal Server Error</div>,
defaultNotFoundComponent: () => <div>Not Found</div>,
scrollRestoration: true,
});
return router;
}
路由工厂配置了预加载行为、滚动恢复以及默认的错误/未找到组件。
4. 创建根路由
根路由定义了你的 HTML 外壳,包含 head 管理和脚本:
src/routes/__root.tsx
/// <reference types="vite/client" />
import { HeadContent, Link, Scripts, createRootRoute } from "@tanstack/react-router";
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools";
import * as React from "react";
import appCss from "~/styles/app.css?url";
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: "utf8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
],
links: [{ rel: "stylesheet", href: appCss }],
scripts: [{ src: "/customScript.js", type: "text/javascript" }],
}),
errorComponent: () => <h1>500: Internal Server Error</h1>,
notFoundComponent: () => <h1>404: Page Not Found</h1>,
shellComponent: RootDocument,
});
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html>
<head>
<HeadContent />
</head>
<body>
<div className="p-2 flex gap-2 text-lg">
<Link to="/" activeProps={{ className: "font-bold" }} activeOptions={{ exact: true }}>
Home
</Link>{" "}
<Link
// @ts-ignore
to="/this-route-does-not-exist"
activeProps={{ className: "font-bold" }}
>
404
</Link>
</div>
<hr />
{children}
<TanStackRouterDevtools position="bottom-right" />
<Scripts />
</body>
</html>
);
}
在 head() 函数中定义 meta 标签、样式表和脚本。shellComponent 提供了包裹所有页面的 HTML 文档外壳。使用 HeadContent 渲染 head 配置,使用 Scripts 注入用于水合的客户端 JavaScript。
5. 创建页面路由
页面路由定义了你的应用页面:
src/routes/index.tsx
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({ component: Home });
function Home() {
return (
<div className="p-2">
<h3>欢迎回家!</h3>
<a href="/api/test">/api/test</a>
</div>
);
}
API 路由
TanStack Start 支持 API 路由与页面路由并存。在 src/routes/api/ 中创建文件以定义 Nitro 自动提供服务的端点。