首页
/ React Router + shadcn/ui 模板实战:搭建可服务渲染的 React 组件化项目

React Router + shadcn/ui 模板实战:搭建可服务渲染的 React 组件化项目

2026-09-04 16:43:33作者:申梦珏Efrain

本文基于仓库中的 templates/react-router-app/README.md 展开,完整讲解 shadcn/ui 官方提供的 React Router 项目模板。该模板将 React Router v7、Vite 8、Tailwind CSS v4 与 TypeScript 预配置为一个可直接运行的起步项目,并默认内置 shadcn/ui 组件体系。读完后,你将掌握:如何在该模板中通过 CLI 添加组件、如何正确引入并使用组件、以及模板背后 SSR、路由与构建配置的实际工作方式,从而把「空项目」快速推进到可交付的应用状态。

模板定位与技术栈

README 对该模板的定义是:一个基于 React、TypeScript 与 shadcn/ui 的新 React Router 项目模板(a template for a new React Router project with React, TypeScript, and shadcn/ui)。它解决的是「从零开始配置 SSR + Tailwind + 组件库」这类繁琐的初始工作,把这些约定固化在模板里。

package.json 可以看到模板锁定的技术栈与脚本命令:

依赖 版本 作用
react-router / @react-router/dev 7.15.1 框架本体与开发工具链(dev/build/typegen)
@react-router/node@react-router/serve 7.15.1 Node 平台适配层与生产环境静态/SSR 服务
react / react-dom ^19.2.6 React 19
vite ^8 构建工具
tailwindcss + @tailwindcss/vite ^4 Tailwind CSS v4(Vite 插件方式接入,无需 PostCSS 配置)
typescript ^6 类型系统
isbot ^5 机器人访问检测(React Router SSR 常用能力)

脚本方面提供了五条命令,覆盖了完整开发生命周期:

"scripts": {
  "build": "react-router build",
  "dev": "react-router dev",
  "start": "react-router-serve ./build/server/index.js",
  "typecheck": "react-router typegen && tsc",
  "format": "prettier --write \"**/*.{ts,tsx}\""
}

值得注意的两点:

  • typecheck 会先执行 react-router typegen 再生成 .react-router/types 下的类型声明(如 +types/root+types/home),然后才运行 tsc。这正是 root.tsximport type { Route } from "./+types/root" 能够被识别的原因。
  • start 直接指向 ./build/server/index.js,说明构建产物是分离的 server 入口,生产环境由 @react-router/serve 独立托管。

项目结构与关键文件

模板的文件组织遵循 React Router v7 的 app/ 目录约定:

templates/react-router-app/
├── app/
│   ├── routes/
│   │   └── home.tsx        # 首页路由,已内置一个 shadcn/ui Button
│   ├── routes.ts           # 路由表
│   ├── root.tsx            # 根布局 Layout + ErrorBoundary
│   └── app.css             # Tailwind 入口
├── public/
│   └── favicon.ico
├── Dockerfile              # 多阶段构建部署配置
├── react-router.config.ts  # React Router 框架配置
├── tsconfig.json           # 含 ~ 路径别名
├── vite.config.ts          # Vite 插件链
└── package.json

路由表:routes.ts

app/routes.ts 采用「集中式路由配置」而非文件系统约定路由:

import { type RouteConfig, index } from "@react-router/dev/routes"

export default [index("routes/home.tsx")] satisfies RouteConfig

新增页面时,向该数组追加路由即可,路由结构一目了然,便于团队统一管理。

根布局:root.tsx

app/root.tsx 是 React Router 框架层的约定入口,包含三部分:

  1. Layout 组件:渲染完整 HTML 骨架,在 <head> 中注入 <Meta /><Links />(由各路由导出的 meta/links 数据驱动),在 <body> 末尾挂载 <ScrollRestoration />(滚动位置恢复)与 <Scripts />(水合脚本)。
  2. 默认导出 App:仅返回 <Outlet />,作为子路由的挂载点。
  3. ErrorBoundary:模板内置了错误兜底逻辑——通过 isRouteErrorResponse(error) 区分 404 与一般路由错误并给出不同文案;在开发环境(import.meta.env.DEV)下还会把 error.message 与完整 error.stack 渲染到页面上,方便调试。

这套结构让每个新页面天然具备错误边界与滚动恢复能力,无需额外配置。

首页:已预置一个组件示例

app/routes/home.tsx 并非空白页,而是「活文档」:

import { Button } from "~/components/ui/button"

export default function Home() {
  return (
    <div className="flex min-h-svh p-6">
      <div className="flex max-w-md min-w-0 flex-col gap-4 text-sm leading-loose">
        <div>
          <h1 className="font-medium">Project ready!</h1>
          <p>You may now add components and start building.</p>
          <p>We&apos;ve already added the button component for you.</p>
          <Button className="mt-2">Button</Button>
        </div>
      </div>
    </div>
  )
}

它完成了两件事:一是声明式地告诉开发者「现在可以开始添加组件了」,二是用真实的 Button 组件演示了「引入—使用」的完整闭环,同时其布局类(flex min-h-svhgap-4text-sm leading-loose)也示范了 Tailwind v4 在模板中的直接可用性。

添加组件:shadcn CLI 工作流

继承 README 的核心操作步骤:向应用添加 shadcn/ui 组件,运行如下命令:

npx shadcn@latest add button

README 说明该命令会把 ui 组件放置到 components 目录中。结合本模板的结构约定,组件最终落在 app/components/ui/ 下,因为:

  • tsconfig.json 定义了路径别名 "~/*": ["./app/*"],即 ~ 指向 app/ 目录;
  • vite.config.ts 开启了 resolve.tsconfigPaths: true,让 Vite 在打包阶段也能解析 tsconfig 中声明的别名,保证 dev/build 行为一致。

因此模板中组件的实际导入写法是:

import { Button } from "~/components/ui/button"

这正是 home.tsx 使用的形式。需要注意 README 中给出的通用写法:

import { Button } from "@/components/ui/button";

这是 shadcn/ui 面向多数框架(Next.js、Vite 等)的 @/ 别名惯例。在本模板里,从 tsconfig.json 的路径映射看,实际生效的别名是 ~ 而非 @。如果你习惯 @/ 前缀,需要自行在 tsconfig.jsonpaths 中补一条 "@/*": ["./app/*"] 映射,Vite 侧已启用 tsconfigPaths 无需改动。

配置解析:让 SSR 与 Tailwind 开箱即用

react-router.config.ts

react-router.config.ts 内容极简但关键:

import type { Config } from "@react-router/dev/config"

export default {
  // Config options...
  // Server-side render by default, to enable SPA mode set this to `false`
  ssr: true,
} satisfies Config

ssr: true 表明模板默认开启服务端渲染;配置文件内注释也明确提示:若希望切换为纯 SPA 模式,将该值改为 false 即可。这对需要 SEO 的服务端渲染场景是默认最优解,对纯客户端应用则留了开关。

vite.config.ts

vite.config.ts 只有四行有效配置:

import { reactRouter } from "@react-router/dev/vite"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig } from "vite"

export default defineConfig({
  resolve: { tsconfigPaths: true },
  plugins: [tailwindcss(), reactRouter()],
})

两个 Vite 插件各司其职:tailwindcss() 以插件方式处理 Tailwind v4 的 CSS(v4 不再需要 tailwind.config.js 与 PostCSS 配置);reactRouter() 提供开发服务器、预渲染、构建产物拆分等框架能力。resolve.tsconfigPaths 则如前文所述,打通了 ~ 别名在构建时的解析。

app.css

样式入口 app/app.css 只有一行 @import "tailwindcss";,并在 root.tsx 中通过 import "./app.css" 挂到应用全局——这是 Tailwind CSS v4 的标准入口方式,之后所有 className 工具类(如 home.tsx 中的 min-h-svh)即可全局生效。

Docker 部署

模板附带了一份 Dockerfile,采用经典的三阶段 + 生产镜像分层构建:

  1. development-dependencies-env:完整 npm ci 安装含 devDependencies 的 node_modules(供构建使用);
  2. production-dependencies-env:仅 npm ci --omit=dev 安装生产依赖,保证运行镜像最小化;
  3. build-env:复用开发依赖执行 npm run build,产出 ./build 目录;
  4. 最终镜像:基于 node:20-alpine,只复制 package.json、生产依赖与 build/ 产物,CMD ["npm", "run", "start"] 即启动 react-router-serve ./build/server/index.js

这套分层策略把构建依赖与运行依赖彻底隔离,最终镜像不包含 devDependencies 与源码,适合生产环境直接部署。

小结

回到 README 本身给出的两条核心操作,现在可以完整理解其背后的工程支撑:

  • 添加组件npx shadcn@latest add button,组件写入 components 目录(本模板中即 app/components/ui/,配合 ~ 别名);
  • 使用组件:从 ~/components/ui/button(或按 README 惯例配置后的 @/components/ui/button)导入,在任意路由组件中直接使用。

模板的价值在于把「React Router v7 SSR + Tailwind v4 + TypeScript + shadcn/ui」的初始配置全部预置好——路由表、根布局与错误边界、类型生成、Vite 插件链、Docker 多阶段构建——开发者拿到模板后即可把精力放在业务与组件本身,而不是脚手架配置。如需对比其他框架的起步模板,可以参阅同目录下的 templates/next-apptemplates/vite-app 等模板。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
981
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384