首页
/ shadcn/ui vite-app 模板详解:React + TypeScript + Vite 项目初始化与组件接入实战

shadcn/ui vite-app 模板详解:React + TypeScript + Vite 项目初始化与组件接入实战

2026-09-04 10:09:11作者:伍希望

本文围绕 shadcn/ui 仓库中 templates/vite-app 目录下的 Vite 模板展开:先解读该模板的工程配置(Vite 插件、Tailwind CSS v4、@ 路径别名、TypeScript 项目引用),再完整覆盖 README 中「添加组件」与「使用组件」两步操作,并结合模板源码深入剖析入口挂载、暗色主题切换等实现细节,帮助你在 Vite 环境中从零搭建一个可直接接入 shadcn/ui 组件库的 React + TypeScript 项目。

模板定位:什么时候使用 vite-app 模板

templates/vite-app/README.md 对该模板的定义非常直接:

This is a template for a new Vite project with React, TypeScript, and shadcn/ui.

也就是说,当你满足以下条件时,这个模板是最省事的选择:

  • 使用 Vite(而非 Next.js、Astro、React Router 等其他框架)作为构建工具;
  • 技术栈为 React + TypeScript
  • 希望开箱即用地接入 shadcn/ui 组件体系,省去手动配置 Tailwind CSS、路径别名等前置工作。

shadcn/ui 官方文档中也提供了 npx shadcn@latest init 这类交互式初始化方式,vite-app 正是该初始化流程在 Vite 项目形态下所落地的标准模板之一。仓库根目录下的 scripts/sync-templates.sh 脚本负责把本仓库中的 templates/vite-app 内容同步到对应的独立模板仓库(脚本采用「克隆 → 清空 → 全量覆盖」的策略,以原子化方式处理文件的新增、变更与删除),因此你在其他地方获取到的 shadcn/ui Vite 模板,其配置与这里的源码完全同源。

模板目录结构

当前模板的完整结构如下,每个文件都在下文中对应解读:

templates/vite-app/
├── index.html                  # 入口 HTML,挂载 #root
├── package.json                # 依赖与 npm scripts
├── tsconfig.json               # 项目引用 + 全局 paths
├── tsconfig.app.json           # 应用代码的 TS 配置
├── tsconfig.node.json          # 构建工具链代码的 TS 配置
├── vite.config.ts              # Vite 插件与路径别名
├── eslint.config.js            # ESLint flat config
├── public/vite.svg             # 页面 favicon
└── src/
    ├── main.tsx                # React 入口,挂载 App 与 ThemeProvider
    ├── App.tsx                 # 示例页面,已内置 button 组件用法
    ├── index.css               # Tailwind CSS v4 入口
    ├── assets/react.svg
    └── components/
        └── theme-provider.tsx  # 暗色/亮色/跟随系统主题 Provider

注意一个细节:模板的 src/components/ 目录中只预置了 theme-provider.tsx,并没有 ui/ 子目录——UI 组件(如 ui/button)是由 npx shadcn@latest add 命令在本地生成并写入的,这正体现了 shadcn/ui「组件源码直接落在你项目里」的核心理念。

工程配置逐项解读

Vite 配置:React 与 Tailwind 双插件 + @ 别名

vite.config.ts 内容非常简洁,但每一行都不可少:

import path from "path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"

// https://vite.dev/config/
export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
})

关键配置点:

  • @tailwindcss/vite 插件:Tailwind CSS v4 官方推荐的 Vite 集成方式,替代了 v3 时代的 PostCSS + tailwind.config.js 链路,模板中因此看不到独立的 Tailwind 配置文件;
  • @ 别名指向 ./src:这是 README 中 import { Button } from "@/components/ui/button" 这一写法能成立的底层依据。

Tailwind CSS v4 的入口写法

src/index.css 全部只有一行:

@import "tailwindcss";

这正是 Tailwind CSS v4 的标志性入口——通过 CSS @import 直接引入核心,无需 v3 中的 @tailwind base / components / utilities 三行指令。

TypeScript 项目引用与路径映射

模板采用了 TS 的「project references」方案:

  • tsconfig.json 不直接包含源码,而是通过 references 分别引用 tsconfig.app.json(应用代码)与 tsconfig.node.json(Vite 配置等工具链代码),同时在全局声明 "@/*": ["./src/*"]
  • tsconfig.app.json 针对应用代码开启了 strictnoUnusedLocalsnoUnusedParametersverbatimModuleSyntaxerasableSyntaxOnly 等严格选项,targetes2023moduleResolutionbundler,并在其中再次声明了相同的 paths 别名,保证 IDE 与类型检查两端行为一致。

package.json:依赖版本与可用脚本

package.json 中的核心依赖:

依赖 版本 作用
react / react-dom ^19.2.6 React 19 运行时
tailwindcss ^4 Tailwind CSS v4
@tailwindcss/vite ^4 Tailwind v4 的 Vite 插件
vite ^8 构建工具
@vitejs/plugin-react ^6 React 快刷新支持
typescript ~6 类型检查
prettier-plugin-tailwindcss ^0.8.0 格式化时自动排序 Tailwind 类名

对应的 npm scripts 提供了完整的本地开发闭环:

pnpm dev         # 启动 Vite 开发服务器
pnpm build       # tsc -b && vite build(先类型检查再打包)
pnpm lint        # eslint .
pnpm typecheck   # tsc --noEmit
pnpm format      # prettier 写入格式化
pnpm preview     # 本地预览生产构建产物

其中 build 脚本把 tsc -b(增量类型检查整个项目引用图)放在 vite build 之前,意味着类型错误会直接阻断生产构建,这是模板内置的质量门禁。

添加组件:npx shadcn@latest add

这是 README 的第一个核心操作。在已初始化好 shadcn/ui 的项目中执行:

npx shadcn@latest add button

执行效果:

  1. CLI 从 registry 拉取 button 组件的源码;
  2. 将其写入项目的 src/components 目录(因为模板通过 @ 别名与 tsconfig paths 将 @ 映射到 ./src,最终组件落在 src/components/ui/button.tsx);
  3. 同时把组件依赖的图标、工具函数等一并写入对应位置。

组件源码直接属于你的项目,可以随意阅读与修改——这也是它与「安装一个 npm 组件包」的本质区别。

使用组件:通过 @ 别名导入

README 的第二个核心操作是导入方式:

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

模板自带的 src/App.tsx 就是一个真实可用的最小示例,它还贴心地预置了 button 组件的引用:

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

export function App() {
  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 className="font-mono text-xs text-muted-foreground">
          (Press <kbd>d</kbd> to toggle dark mode)
        </div>
      </div>
    </div>
  )
}

这里还能看到 shadcn/ui 组件的典型样式特征:text-muted-foreground 这类语义化颜色 token(由 Tailwind v4 主题变量驱动),以及 min-h-svh 等现代布局工具类。

入口挂载与暗色主题:源码级细节

应用入口

src/main.tsx 展示了标准的 React 19 挂载方式,并把整个应用包在 ThemeProvider 内:

import { StrictMode } from "react"
import { createRoot } from "react-dom/client"

import "./index.css"
import App from "./App.tsx"
import { ThemeProvider } from "@/components/theme-provider.tsx"

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </StrictMode>
)

入口 HTML 为 index.html,结构是最简的 <div id="root"> + <script type="module" src="/src/main.tsx">

ThemeProvider:三种主题、localStorage 与快捷键切换

src/components/theme-provider.tsx 是模板预置的暗色主题方案,支持 dark / light / system 三种取值,值得关注的实现细节有:

  • 初始化优先级:先读 localStorage(key 默认为 theme),无效值则回退到 defaultTheme(默认 "system");
  • system 模式:通过 window.matchMedia("(prefers-color-scheme: dark)") 解析真实明暗值,并监听媒体查询的 change 事件,系统主题变化时实时跟随;
  • 切换防闪烁disableTransitionsTemporarily() 会在换肤瞬间临时注入一条禁用全部 transition 的样式,双 requestAnimationFrame 后再移除,避免整个页面在明暗切换时产生过渡动画残影;
  • 快捷键 d:App 页面提示「Press d to toggle dark mode」,其实现就在 Provider 内——监听全局 keydown,并做了三重保护:忽略 event.repeat 连按、忽略带 meta/ctrl/alt 修饰键的组合、忽略可编辑输入目标(inputtextareaselectcontenteditable);
  • 跨标签页同步:监听 windowstorage 事件,当其他标签页修改了同一 storageKey 时同步本地状态;
  • 对外 API:组件通过 Context 暴露 themesetTheme,并提供 useTheme() hook(在 Provider 外调用会抛出明确错误)。

ThemeProvider 还支持 defaultThemestorageKeydisableTransitionOnChange 等 props,按项目需要覆盖即可。

模板的同步机制:为什么模板内容与仓库强一致

仓库根目录的 scripts/sync-templates.sh 揭示了模板的分发方式:

# 简化自 scripts/sync-templates.sh
# 对本仓库每个 template 目录:
# 1. 克隆对应的外部只读模板仓库(--depth 1)
# 2. 清空克隆目录内容
# 3. 将本仓库模板内容全量拷贝过去
# 4. 有变更则提交并推送(复用本次 commit message)

这种「克隆 → 清空 → 全量覆盖」的策略能无差别地处理文件的新增、修改与删除,保证外部模板仓库与本仓库中的 templates/vite-app 逐字节一致。从源码结构看,这正是该模板能够被 shadcn 的初始化/脚手架流程(如 npx shadcn@latest init 选择 Vite 框架时)直接消费的前提。

小结

templates/vite-app 提供了一个「配置零负担」的 shadcn/ui 起步环境:

  1. vite.config.ts 中已配好 @tailwindcss/vite@./src 别名,是组件导入写法成立的基础;
  2. Tailwind CSS v4 通过单行 @import "tailwindcss" 接入,无需额外配置文件;
  3. 添加组件只需 npx shadcn@latest add <name>,源码直接落入 src/components
  4. 使用组件通过 import { X } from "@/components/ui/x" 完成;
  5. 模板预置的 ThemeProvider 覆盖了明暗主题、系统跟随、快捷键切换与跨标签同步,App.tsx 则给出了可直接运行的最小示例;
  6. build 脚本内置 tsc -b 类型检查门禁,配合 linttypecheckpreview 脚本构成完整的本地开发闭环。

如需对比其他框架形态(Next.js、Astro、React Router、Turborepo monorepo 等),可参考同级的 templates/next-app/README.mdtemplates/astro-app/README.mdtemplates/react-router-app/README.mdtemplates/vite-monorepo/README.md

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

项目优选

收起
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
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384