从Next.js迁移到TanStack Router的完整指南

从Next.js迁移到TanStack Router的完整指南

router TanStack/router: TanStack Router(前身为React Training的React Router)是一个强大的客户端路由库,适用于构建单页应用(SPA)。它使得React应用能够根据URL的变化来更新视图,实现页面间的无刷新跳转。 router 项目地址: https://gitcode.com/gh_mirrors/ro/router

前言

在现代前端开发中,路由管理是构建单页应用(SPA)的核心部分。TanStack Router作为新一代的路由解决方案,提供了更灵活、更强大的路由功能。本文将详细介绍如何从Next.js迁移到TanStack Router,帮助开发者理解两者之间的差异并顺利完成迁移。

准备工作

在开始迁移前,确保你的项目结构符合以下标准:

项目目录结构
├── package.json
├── src
│   └── app
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.tsx
│       └── page.tsx
└── tsconfig.json

如果你的项目结构不同,需要先调整到类似结构。这个结构代表了典型的Next.js应用布局,使用App Router模式。

迁移步骤详解

第一步:移除Next.js相关依赖

首先需要清理Next.js特有的依赖和配置文件:

npm uninstall @tailwindcss/postcss next
rm postcss.config.* next.config.*

这一步会移除Next.js核心包和相关的构建配置。

第二步:安装TanStack Router和Vite

TanStack Router需要搭配Vite使用,安装必要的依赖:

npm i @tanstack/react-router@alpha @tanstack/react-start@alpha vite
npm i -D @tailwindcss/vite tailwindcss vite-tsconfig-paths

这里安装了:

  • TanStack Router核心库
  • TanStack Start集成工具
  • Vite构建工具
  • Tailwind CSS相关支持

第三步:配置Vite项目

更新项目配置文件以适应新的构建系统:

  1. 修改package.json
{
  "type": "module",
  "scripts": {
    "dev": "vite dev",
    "build": "vite build",
    "start": "node .output/server/index.mjs"
  }
}
  1. 创建vite.config.ts
import tailwindcss from '@tailwindcss/vite'
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
  server: {
    port: 3000,
  },
  plugins: [
    tailwindcss(),
    tsconfigPaths(),
    tanstackStart({
      tsr: {
        routesDirectory: 'src/app',
      },
    }),
  ],
})

关键点说明:

  • routesDirectory指定了路由文件目录,保持与Next.js一致的src/app
  • 集成了Tailwind CSS支持
  • 启用了路径别名解析

第四步:重构根布局

Next.js使用layout.tsx作为根布局,TanStack Router使用__root.tsx

import {
  Outlet,
  createRootRoute,
  HeadContent,
  Scripts,
} from "@tanstack/react-router"
import "./globals.css"

export const Route = createRootRoute({
  head: () => ({
    meta: [
      { charSet: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      { title: "TanStack Start Starter" }
    ],
  }),
  component: RootLayout,
})

function RootLayout() {
  return (
    <html lang="en">
      <head>
        <HeadContent />
      </head>
      <body>
        <Outlet />
        <Scripts />
      </body>
    </html>
  )
}

主要变化:

  • 使用createRootRoute创建根路由
  • 通过head配置替代Next.js的metadata
  • 使用Outlet作为子路由的渲染出口

第五步:重构首页

将Next.js的page.tsx转换为TanStack Router的index.tsx

export const Route = createFileRoute({
  component: Home,
})

function Home() {
  return (
    <main className="min-h-dvh w-screen flex items-center justify-center flex-col gap-y-4 p-4">
      <img
        className="max-w-sm w-full"
        src="https://raw.githubusercontent.com/tanstack/tanstack.com/main/src/images/splash-dark.png"
        alt="TanStack Logo"
      />
      <h1>
        <span className="line-through">Next.js</span> TanStack Start
      </h1>
      <a
        className="bg-foreground text-background rounded-full px-4 py-1 hover:opacity-90"
        href="https://tanstack.com/start/latest"
        target="_blank"
      >
        Docs
      </a>
    </main>
  )
}

关键变化:

  • 使用createFileRoute定义路由
  • 组件不再需要默认导出

第六步:创建路由配置

src/router.tsx中定义应用路由:

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

export function createRouter() {
  const router = createTanStackRouter({
    routeTree,
    scrollRestoration: true,
  })

  return router
}

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

这个文件是TanStack Router的核心配置,可以在这里设置:

  • 路由预加载策略
  • 数据缓存策略
  • 滚动恢复行为等

第七步:验证迁移

运行开发服务器:

npm run dev

访问http://localhost:3000,应该能看到应用正常运行。

高级迁移指南

路由结构对比

| 路由类型 | Next.js路径 | TanStack Router路径 | |---------------|----------------------------|--------------------------| | 根布局 | src/app/layout.tsx | src/app/__root.tsx | | 首页 | src/app/page.tsx | src/app/index.tsx | | 静态路由 | src/app/posts/page.tsx | src/app/posts.tsx | | 动态路由 | src/app/posts/[slug]/page.tsx | src/app/posts/$slug.tsx | | 全匹配路由 | src/app/posts/[...slug]/page.tsx | src/app/posts/$.tsx | | API路由 | src/app/api/endpoint/route.ts | src/app/api/endpoint.ts |

动态路由参数获取

在TanStack Router中获取动态参数:

export const Route = createFileRoute({
  component: Page,
})

function Page() {
  const { slug } = Route.useParams()
  return <div>My Post: {slug}</div>
}

对于全匹配路由,使用_splat获取参数:

const { _splat } = Route.useParams()

链接组件

TanStack Router提供了自己的Link组件:

import { Link } from "@tanstack/react-router"

function Component() {
  return <Link to="/dashboard">Dashboard</Link>
}

服务端功能

TanStack Router的服务端函数定义:

import { createServerFn } from "@tanstack/react-start"

export const create = createServerFn().handler(async () => {
  return true
})

字体处理

替代Next.js的字体方案,使用CSS优先方法:

  1. 安装字体包:
npm i -D @fontsource-variable/dm-sans @fontsource-variable/jetbrains-mono
  1. 在CSS中引入:
@import '@fontsource-variable/dm-sans';
@import '@fontsource-variable/jetbrains-mono';

@theme inline {
  --font-sans: 'DM Sans Variable', sans-serif;
  --font-mono: 'JetBrains Mono Variable', monospace;
}

数据获取

TanStack Router推荐使用路由加载器:

export const Route = createFileRoute({
  component: Page,
  loader: async () => {
    const res = await fetch('https://api.example.com/blog')
    return res.json()
  },
})

function Page() {
  const posts = Route.useLoaderData()

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

总结

从Next.js迁移到TanStack Router涉及多个方面的调整,包括路由定义、布局系统、数据获取等。本文详细介绍了每个关键步骤的转换方法,帮助开发者理解两种路由系统的差异。TanStack Router提供了更灵活的路由配置和更强大的功能,适合需要精细控制路由行为的中大型应用。

迁移完成后,你可以充分利用TanStack Router提供的先进特性,如嵌套路由、精细的路由预加载和数据缓存策略等,来提升应用性能和开发体验。

router TanStack/router: TanStack Router(前身为React Training的React Router)是一个强大的客户端路由库,适用于构建单页应用(SPA)。它使得React应用能够根据URL的变化来更新视图,实现页面间的无刷新跳转。 router 项目地址: https://gitcode.com/gh_mirrors/ro/router

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宣万歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值