跳到主要内容

Start 入门

第一次看 TanStack Start,很容易把注意力全放在“它支持哪些高级能力”上。更有用的方式其实是先别急着背功能,先把项目骨架和运行主线看顺。

起步方式

按官方 Getting Started 页面,现在最常见的起步方式有三条:

  • TanStack Builder
  • TanStack CLI
  • 从官方示例项目开始

最小创建命令

npx @tanstack/cli@latest create

CLI 会让你选:

  • 包管理器
  • 是否加 Tailwind CSS
  • 是否加 ESLint
  • 目标模板

如果你只是想先理解 Start 的骨架,建议先选最轻的模板,别一上来把鉴权、UI 库、数据库一起带上。

从示例起步也很实用

npx gitpick TanStack/router/tree/main/examples/react/start-basic my-start-app
cd my-start-app
npm install
npm run dev

这个方式的好处很直接:打开就是一个能跑的项目,routes、入口文件、插件配置都已经摆好了。

先接受一个前提:它是 Router-first

TanStack Start 不是“先有框架,再顺手配个路由”。它的出发点刚好相反:

  • 路由系统用 TanStack Router
  • 再在这个基础上补服务端执行、渲染、构建与部署

所以你在 Start 里看到的很多概念,最后都会回到 Router:

  • 文件路由
  • loader
  • beforeLoad
  • 预加载
  • 搜索参数
  • 路由上下文

如果你已经用过 TanStack Router,上手会快很多。没用过也没关系,只是建议别跳过 Router 那组文档。

先认目录

1. src/routes

这是核心中的核心。

Start 延续了 Router 的文件路由习惯。页面、布局、参数路由、部分服务端处理,最后都围着这里组织。你可以把它理解成“应用结构图”,很多项目一眼看过去,复杂度先在这里暴露出来。

2. 应用入口和 Start 实例

官方文档里会提到 createStartserver entry pointclient entry point 这些东西。它们决定的是:

  • 默认怎么做 SSR
  • 请求进来之后,服务端从哪里接住
  • 客户端最后怎么 hydrate

这部分不像业务代码天天改,但它定义了整套应用“怎么跑起来”。

3. Server Functions 和 Server Routes

这两类能力很容易被混着理解,实际上它们面对的问题不同:

  • Server Functions 更像类型安全的 RPC 调用
  • Server Routes 更像原始 HTTP 端点

后面那篇服务端文档会专门拆开讲。

一个最小骨架长什么样

下面这个例子不是官方脚手架原样照抄,而是把你第一次上手最该看的几个文件压成最小集合。

vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'

export default defineConfig({
plugins: [
tanstackStart({
tsr: {
srcDirectory: 'src',
routesDirectory: 'routes',
generatedRouteTree: 'routeTree.gen.ts',
},
}),
react(),
],
})

先看这段配置有两个目的:

  • 确认 Start 不是一个独立构建系统,它是贴在 Vite 上工作的
  • 确认路由树是通过插件参与生成的,不是你手写一整棵大对象

src/router.tsx

import { createRouter } from '@tanstack/react-router'
import { routeTree } from './routeTree.gen'

export function getRouter() {
return createRouter({
routeTree,
defaultPreload: 'intent',
scrollRestoration: true,
})
}

declare module '@tanstack/react-router' {
interface Register {
router: ReturnType<typeof getRouter>
}
}

这段代码很值得多看两眼:

  • routeTree 来自生成文件
  • defaultPreload: 'intent' 是很常见的体验优化默认值
  • Register 这段声明是 TanStack 体系里很典型的类型接线方式

src/routes/__root.tsx

import { createRootRoute, Link, Outlet } from '@tanstack/react-router'

export const Route = createRootRoute({
component: RootLayout,
})

function RootLayout() {
return (
<html lang="zh-CN">
<body>
<nav style={{ display: 'flex', gap: 12 }}>
<Link to="/">首页</Link>
<Link to="/posts">文章</Link>
</nav>
<Outlet />
</body>
</html>
)
}

Start 项目里,根路由往往就承担了 html / body / layout / provider 这些最外层结构。

src/routes/index.tsx

import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/')({
component: HomePage,
})

function HomePage() {
return <h1>Hello TanStack Start</h1>
}

这就是最基础的一条页面路由。

再看一个带数据的页面

import { createFileRoute } from '@tanstack/react-router'

async function fetchPosts() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5')

if (!res.ok) {
throw new Error('文章获取失败')
}

return res.json() as Promise<Array<{ id: number; title: string }>>
}

export const Route = createFileRoute('/posts')({
loader: async () => {
const posts = await fetchPosts()
return { posts }
},
component: PostsPage,
})

function PostsPage() {
const { posts } = Route.useLoaderData()

return (
<main>
<h1>文章列表</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</main>
)
}

这段代码已经能把 Start 的一个核心手感体现出来:

  • 页面和路由定义放得很近
  • 数据准备和路由绑定
  • 组件直接消费 loader 数据

如果你以前习惯的是“组件里 useEffect 发请求”,那这里的阅读方式会有明显变化。

和 Next 的第一层映射

如果你以前主要在 Next.js 里工作,可以先这样做一层心智映射:

你熟悉的东西在 Start 里更接近什么
app 目录里的页面与布局src/routes 下的文件路由与根路由
route.ts / API RoutesServer Routes
Server Actions 那套服务器调用心智Server Functions
路由级数据获取loader / beforeLoad
SSR / StreamingStart 的服务端渲染入口与 Router 的 SSR 体系

它不是一一对应,但拿来建立第一层方向感已经很够用。

Start 最吸引人的地方

官方 Overview 里提到的重点能力,最值得你先留意的是这几项:

  • full-document SSR
  • streaming
  • server functions
  • middleware & context
  • full-stack builds

这些词放在一起看,意味着它不是一个只会把 React 页面渲一下的工具,而是在认真处理“前后端同仓、同路由体系、同类型系统”这件事。

第一次上手建议

  1. 跑一个最小示例
  2. 只盯 src/routes、入口文件、一个 Server Function、一个 Server Route
  3. 先验证“我知道请求是怎么流动的”
  4. 再去看缓存、SSR、ISR、Selective SSR 这些更细的能力

先把主线看清,后面的文档才不会读成一堆零散 feature。