尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

在 Nitro 中使用 TanStack Start 实现 React 全栈 SSR(Vite 插件集成指南)

发布时间:2026/9/15 19:07:05

资讯中心
01
ARTICLE

在 Nitro 中使用 TanStack Start 实现 React 全栈 SSR(Vite 插件集成指南)

在 Nitro 中使用 TanStack Start 实现 React 全栈 SSR(Vite 插件集成指南)
在 Nitro 中使用 TanStack Start 实现 React 全栈 SSRVite 插件集成指南【免费下载链接】nitroNext Generation Server Toolkit. Create web servers with everything you need and deploy them wherever you prefer.项目地址: https://gitcode.com/GitHub_Trending/ni/nitro本文基于 Nitro 仓库中的 vite-ssr-tss-react 示例 与配套文档 docs/4.examples/vite-ssr-tss-react.md 编写。你将学会如何通过 Nitro 的 Vite 插件把 TanStack StartTanStack Router React接入 Nitro构建一个具备服务端渲染SSR、文件路由File-based Routing与内建 API 路由API Routes的 React 全栈应用并最终产出可部署到任意平台的生产构建。TanStack Start 是一套面向 React 的全栈框架方案而 Nitro 则是一个下一代服务端工具包Next Generation Server Toolkit它可以作为 Vite 插件直接嵌入前端构建链路为你同时提供 API 路由、SSR 渲染与可移植的生产构建。本指南以仓库中的完整示例为骨架逐步拆解从 Vite 配置、服务端入口到路由与 API 端点的全部接入细节并结合 Nitro 源码解释背后的运行机制让你既能照抄落地也能理解原理。为什么用 Nitro 承载 TanStack StartNitro 以 Vite 插件的形式工作在vite.config中加入nitro()插件即可在现有 Vite 项目中获得一个完整的服务端——包括 API 路由、服务端渲染以及可部署到任何平台的生产构建详见 Vite 集成文档。这与 TanStack Start 的文件路由 SSR API全栈诉求天然互补vite dev同时启动前端与后端Nitro 提供服务端路由与静态资源Vite 负责客户端模块服务端代码运行在独立 worker 中并自动热重载vite build将客户端与服务端一起打包进单一的.output/目录配合任意部署预设即可上线Nitro 会注册client、nitro环境并在检测到 SSR 入口时额外注册ssr环境见 docs/1.docs/61.vite.md与 TanStack Start 的服务端入口格式无缝对接。示例的完整目录结构如下对应仓库examples/vite-ssr-tss-react/examples/vite-ssr-tss-react/ ├── package.json ├── server.ts # Nitro 服务端入口TanStack Start handler ├── tsconfig.json # 继承 nitro/tsconfig配置 ~/* 别名 ├── vite.config.mjs # 组合 tanstackStart react tailwindcss nitro 插件 └── src/ ├── router.tsx # 路由工厂函数 ├── routeTree.gen.ts # TanStack Router 自动生成的 route tree ├── routes/ │ ├── __root.tsx # 根路由HTML shell head 管理 │ ├── index.tsx # 首页路由 │ └── api/ │ └── test.ts # API 路由含 server middleware └── styles/ └── app.css # Tailwind 样式1. 配置 Vite组合四个插件首先在vite.config.mjs中同时启用 Nitro、TanStack Start、React 与 Tailwind 插件源码见 examples/vite-ssr-tss-react/vite.config.mjsimport { defineConfig } from vite; import { nitro } from nitro/vite; import { tanstackStart } from tanstack/react-start/plugin/vite; import viteReact from vitejs/plugin-react; import tailwindcss from tailwindcss/vite; export default defineConfig({ plugins: [tanstackStart(), viteReact(), tailwindcss(), nitro()], resolve: { tsconfigPaths: true }, environments: { ssr: { build: { rollupOptions: { input: ./server.ts } } }, }, });配置要点tanstackStart()提供完整的 SSR 集成并自动处理客户端入口client entrynitro()来自nitro/vite导出见 src/vite.ts它内部会返回一组 Nitro Vite 插件nitroInit、nitroEnv、nitroMain、nitroPrepare、nitroDevServiceProxy、nitroPreviewPlugin等见 src/build/vite/plugin.ts负责环境注册、dev server 代理与生产构建resolve: { tsconfigPaths: true }让 Vite 读取 tsconfig 中的路径别名从而支持~/*指向./src/*的导入environments.ssr.build.rollupOptions.input将./server.ts指定为 SSR 环境的构建入口。Nitro 的nitroEnv插件会自动补充nitro与client环境而ssr环境正是承载 TanStack Start 服务端渲染的关键。对应的tsconfig.json见 examples/vite-ssr-tss-react/tsconfig.json继承自nitro/tsconfig并声明了jsx: react-jsx与~/*别名{ extends: nitro/tsconfig, compilerOptions: { baseUrl: ., jsx: react-jsx, paths: { ~/*: [./src/*] } } }2. 创建服务端入口桥接 Nitro 与 TanStack StartNitro 会自动检测项目根目录或serverDir下的server.ts文件并将其作为服务端入口Server Entry用于处理所有未被具体路由匹配的请求详见 服务端入口文档。示例中的 examples/vite-ssr-tss-react/server.ts 内容如下import handler, { createServerEntry } from tanstack/react-start/server-entry; export default createServerEntry({ fetch(request) { return handler.fetch(request); }, });工作方式解读createServerEntry将 TanStack Start 的服务端处理器包装成 Nitro 认可的入口格式默认期望导出带fetch(request: Request): Response方法的 Web 兼容处理器即web格式handler.fetch处理所有进入的请求TanStack Start 自动完成 SSR 渲染、路由匹配与 API 请求转发在 Nitro 的请求生命周期中服务端入口被注册为兜底的/**路由——具体路由如src/routes/下的文件路由与 API 路由优先匹配未匹配的请求才会落入 Server Entry再交由渲染器处理详见 docs/1.docs/6.server-entry.md。注意区分Server Entry 是兜底处理器而非全局中间件。需要作用于每一个请求的横切逻辑鉴权、日志、预处理应使用 中间件 而不是 Server Entry。示例package.json中的脚本见 examples/vite-ssr-tss-react/package.json体现了完整的开发与部署闭环{ type: module, scripts: { build: vite build, dev: vite dev, start: node .output/server/index.mjs }, dependencies: { tanstack/react-router: ^1.168.8, tanstack/react-router-devtools: ^1.166.11, tanstack/react-start: ^1.167.13, nitro: latest, react: ^19.2.4, react-dom: ^19.2.4, tailwind-merge: ^3.5.0, zod: ^4.3.6 }, devDependencies: { tailwindcss/vite: ^4.2.2, types/node: latest, types/react: ^19.2.14, types/react-dom: ^19.2.3, vitejs/plugin-react: ^6.0.1, tailwindcss: ^4.2.2, typescript: ^6.0.2, vite: latest } }npm run dev→vite dev前后端一体化开发服务器npm run build→vite build客户端与服务端一起构建到.output/npm start→node .output/server/index.mjs以 Node 运行时启动生产构建。3. 配置路由器预加载、滚动恢复与兜底组件在src/router.tsx中通过路由工厂函数创建 TanStack Router 实例见 examples/vite-ssr-tss-react/src/router.tsximport { createRouter } from tanstack/react-router; import { routeTree } from ./routeTree.gen.ts; export function getRouter() { const router createRouter({ routeTree, defaultPreload: intent, defaultErrorComponent: () divInternal Server Error/div, defaultNotFoundComponent: () divNot Found/div, scrollRestoration: true, }); return router; }这里配置了三类关键行为defaultPreload: intent按用户交互意图如悬停链接预加载路由数据提升导航感知速度defaultErrorComponent/defaultNotFoundComponent提供全局默认的 500 与 404 兜底 UI避免未捕获异常时出现空白页scrollRestoration: true在客户端路由跳转时恢复滚动位置改善 SPA 体验。注意routeTree来自自动生成的src/routeTree.gen.ts。该文件由 TanStack Router 根据src/routes/目录自动生成包含所有文件路由的类型信息与路由树结构/* eslint-disable */ // ts-nocheck // This file was automatically generated by TanStack Router. // You should NOT make any changes in this file as it will be overwritten. // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from ./routes/__root import { Route as IndexRouteImport } from ./routes/index import { Route as ApiTestRouteImport } from ./routes/api/test const IndexRoute IndexRouteImport.update({ id: /, path: /, getParentRoute: () rootRouteImport, } as any) const ApiTestRoute ApiTestRouteImport.update({ id: /api/test, path: /api/test, getParentRoute: () rootRouteImport, } as any) export interface FileRoutesByFullPath { /: typeof IndexRoute /api/test: typeof ApiTestRoute } export interface FileRoutesByTo { /: typeof IndexRoute /api/test: typeof ApiTestRoute } export interface FileRoutesById { __root__: typeof rootRouteImport /: typeof IndexRoute /api/test: typeof ApiTestRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: / | /api/test fileRoutesByTo: FileRoutesByTo to: / | /api/test id: __root__ | / | /api/test fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute ApiTestRoute: typeof ApiTestRoute } declare module tanstack/react-router { interface FileRoutesByPath { /: { id: / path: / fullPath: / preLoaderRoute: typeof IndexRouteImport parentRoute: typeof rootRouteImport } /api/test: { id: /api/test path: /api/test fullPath: /api/test preLoaderRoute: typeof ApiTestRouteImport parentRoute: typeof rootRouteImport } } } const rootRouteChildren: RootRouteChildren { IndexRoute: IndexRoute, ApiTestRoute: ApiTestRoute, } export const routeTree rootRouteImport ._addFileChildren(rootRouteChildren) ._addFileTypesFileRouteTypes() import type { getRouter } from ./router.tsx import type { createStart } from tanstack/react-start declare module tanstack/react-start { interface Register { ssr: true router: AwaitedReturnTypetypeof getRouter } }这份生成代码还通过模块声明把ssr: true与router类型注册到tanstack/react-start从而让服务端渲染与路由类型在整个应用中保持类型安全。不要手动修改该文件每次新增/删除路由后重新生成即可并建议将其排除在 lint/format 之外。4. 创建根路由HTML 外壳、head 管理与客户端脚本注入根路由src/routes/__root.tsx定义了整页的 HTML 文档外壳见 examples/vite-ssr-tss-react/src/routes/__root.tsx/// reference typesvite/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: widthdevice-width, initial-scale1 }, ], links: [{ rel: stylesheet, href: appCss }], scripts: [{ src: /customScript.js, type: text/javascript }], }), errorComponent: () h1500: Internal Server Error/h1, notFoundComponent: () h1404: Page Not Found/h1, shellComponent: RootDocument, }); function RootDocument({ children }: { children: React.ReactNode }) { return ( html head HeadContent / /head body div classNamep-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 positionbottom-right / Scripts / /body /html ); }关键点head()函数声明 meta 标签、样式表通过?url导入的appCss与脚本HeadContent负责在 SSR 时把这段配置渲染进headshellComponent: RootDocument提供包裹所有页面的 HTML 文档外壳{children}位置即页面内容渲染处Scripts注入客户端 JavaScript 以实现 hydration水合让服务端渲染出的 HTML 在浏览器端变为可交互的 React 应用页内通过Link组件实现客户端导航activeOptions{{ exact: true }}确保只有完全匹配/时才高亮导航中特意放入一个不存在的路由链接用于演示 404 兜底组件。样式文件src/styles/app.css使用 Tailwind CSS v4 的import tailwindcss语法并定义了全局的明暗配色基础层见 examples/vite-ssr-tss-react/src/styles/app.cssimport tailwindcss; layer base { *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--color-gray-200, currentcolor); } } layer base { html { color-scheme: light dark; } * { apply border-gray-200 dark:border-gray-800; } html, body { apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200; } .using-mouse * { outline: none !important; } }5. 创建页面路由页面路由文件放在src/routes/下文件名即路径。首页路由 examples/vite-ssr-tss-react/src/routes/index.tsximport { createFileRoute } from tanstack/react-router; export const Route createFileRoute(/)({ component: Home }); function Home() { return ( div classNamep-2 h3Welcome Home!/h3 a href/api/test/api/test/a /div ); }首页渲染一个指向/api/test的链接用于演示前端页面与 Nitro 提供的 API 端点的联通。API 路由与页面路由并存的服务端端点TanStack Start 支持在src/routes/api/下创建文件来定义服务端 API 端点Nitro 会自动为其提供请求服务。示例中的 examples/vite-ssr-tss-react/src/routes/api/test.ts 还演示了如何附加服务端中间件import { createFileRoute } from tanstack/react-router; import { createMiddleware, json } from tanstack/react-start; const testMiddleware createMiddleware().server(async ({ next }) { const result await next(); result.response.headers.set(x-test, true); return result; }); export const Route createFileRoute(/api/test)({ server: { middleware: [testMiddleware], handlers: { GET: async ({ request }) { return json({ api: works! }); }, }, }, });要点说明server.middleware通过createMiddleware().server(...)定义服务端中间件在next()之后修改响应头此处为所有/api/test响应附加x-test: trueserver.handlers.GET声明 HTTP 方法对应的处理函数json(...)便捷地返回 JSON 响应体——GET /api/test将得到{ api: works! }整个请求链路中这个具体 API 路由优先于 Server Entry 被匹配符合 Nitro 的请求生命周期具体路由routes/命中后直接处理不再落入兜底处理器。部署与运行构建产物是单一可移植的.output/目录。使用 Node 运行时启动npm install npm run build npm start开发调试npm run dev即vite dev前后端一体化热更新TanStack Router Devtools 在开发期以悬浮窗形式提供路由调试positionbottom-right本地预览也可使用vite preview通过 Nitro 提供生产构建的本地预览含静态资源与 WebSocket 支持见 docs/1.docs/61.vite.md平台部署Nitro 支持多种部署预设Node、Bun、Deno、Cloudflare、Vercel、Netlify 等构建产物可原样移植到任意目标平台。小结本指南完整复现了仓库中 vite-ssr-tss-react 示例 的落地路径用nitro()Vite 插件承载 TanStack Start以server.ts服务端入口桥接两者借助文件路由同时管理页面与 API 端点最终产出兼具 SSR、客户端水合与可移植部署的 React 全栈应用。仓库中还有 vite-ssr-react、vite-ssr-vue-router、vite-ssr-solid 等更多框架组合示例见 docs/1.docs/61.vite.md可作为横向参考关于服务端入口的深入机制可继续阅读 服务端入口文档 与 渲染器文档。【免费下载链接】nitroNext Generation Server Toolkit. Create web servers with everything you need and deploy them wherever you prefer.项目地址: https://gitcode.com/GitHub_Trending/ni/nitro创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。