环境与初始化
本页目的: 把 shadcn/ui v4 跑起来 —— 技术栈定案(pnpm + Vite 8 + Tailwind v4 + TypeScript)、创建项目、接入 Tailwind、
init完整流程、 components.json 逐字段解读与启动验证。全部基于本机实测(macOS arm64)。本页是 shadcn/ui 实用系列第 1 篇,下一篇见 组件添加与基本使用。
1. 技术栈定案
| 层 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 运行时 | Node | v24.16.0 | shadcn CLI 要求 Node >= 20.18.1(engines 实测) |
| 包管理器 | pnpm | 11.25.0 | |
| 构建 | Vite(react-ts 模板) | 8.2.2 | rolldown 内核 |
| UI | React | 19.2.8 | |
| 语言 | TypeScript | 7.0.2 | 创建后随首次安装升到 ^7.0.2(模板自带 ~6.0.2) |
| 样式 | Tailwind CSS v4 | 4.3.3 | CSS-first,无 tailwind.config.js |
| Tailwind 插件 | @tailwindcss/vite | 4.3.3 | vite 侧接入 |
| 动画 | tw-animate-css | 1.4.0 | 组件动效(init 自动写入 index.css) |
| shadcn CLI | shadcn | 4.20.1 | 固定版本 -D 装入项目,本地 CLI 跑 init/add(不用 dlx @latest) |
| 基元 | @base-ui/react | 1.7.0 | Base UI(v4 默认 style=base-nova,取代旧版 Radix UI) |
| 工具 | cn | 0.2.4 | cn() 类合并(init 自动安装,4.20 起取代 clsx + tailwind-merge) |
2. 创建项目
创建 + 一次装齐依赖(唯一一次安装;shadcn CLI 用固定版本,不用 latest):
pnpm create vite shadcn-demo --template react-ts --no-interactive
cd shadcn-demo
# 一次装齐:shadcn CLI(固定 4.20.1)+ Tailwind v4 + TypeScript(模板自带 ~6.0.2 一并升到 ^7.0.2)
pnpm add -D shadcn@4.20.1 typescript@^7.0.2 tailwindcss @tailwindcss/vite tw-animate-css
pnpm exec tsc --version # → Version 7.0.2
- 单条
pnpm add即完成唯一一次安装(无需先单独pnpm install、也无需分多次 add),实测装出 TS 7.0.2 / Vite 8.2.2 / Tailwind 4.3.3 / tw-animate-css 1.4.0。 - shadcn CLI 以固定版本装入 devDependencies(实测 4.20.1),第 4 节
init直接用 本地 CLI 运行;dlx shadcn@latest存在版本漂移,不保证与本文行为一致。
说明:create 命令为何带
--no-interactive?create-vite 已改为交互式向导 (实测 create-vite 9.2.0,生成的是 Vite 8.2.2 —— create-vite 自身的 版本号与 Vite 主版本号独立演进,9.2.0 是脚手架工具的版本,≠ Vite 9): 即使指定了--template react-ts(免掉 framework/variant 两步),在交互 终端里 React 模板还会额外追问两个问题:
- Which linter to use? —— Oxlint(默认)/ ESLint
- Install with pnpm and start now? —— 是否自动装依赖并启动 dev server
全部选项都可用 CLI flag 显式指定(非 TTY / CI 脚本环境会自动免交互):
flag 作用 默认 -t, --template react-tsframework / variant — --eslint/--no-eslint选 ESLint / Oxlint(仅 React 模板) Oxlint -i, --immediate/--no-immediate自动装依赖并起 dev server 不装 --overwrite目标目录非空时直接覆盖 报错退出 --no-interactive整体免交互,未指定项全部取默认 非 TTY 自动非交互 实测:默认 linter 为 Oxlint(
pnpm lint→oxlint,零 ESLint 依赖); 加--eslint则生成eslint.config.js+ eslint 10 + typescript-eslint,pnpm lint→eslint .。其余脚手架(Vite 8.2.2 / React 19.2.8 / TS ~6.0.2)两种选择完全一致。
3. 接入 Tailwind v4(CSS-first)
v4 不生成 tailwind.config.js,配置在 CSS 与 vite 插件里完成:
vite.config.ts —— 加 @tailwindcss/vite 插件 + @ 路径别名:
import path from "node:path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
})
tsconfig.app.json —— compilerOptions 加 paths(供 tsc 构建解析 @/*):
tsconfig.json(根,solution-style) —— 也要加同样的 paths(供 shadcn CLI 解析别名、决定组件落盘位置;只配 tsconfig.app.json 的话,init 会把组件 写到项目根 ./@/ 而不是 src/):
src/index.css —— 至少先有:
✅ 完成本节三步后(Tailwind 已装、别名两处配好),init 的 preflight (Tailwind / alias 校验)直接通过,组件按别名写进 src/(见第 4 节)。
4. init 初始化
实测流程输出(shadcn 4.20.1,别名已按第 3 节映射到 src/):
- Preflight checks. ✔
- Verifying framework. ✔ Found Vite.
- Validating Tailwind CSS. ✔ Found v4.
- Validating import alias. ✔
- Writing components.json. ✔
- Checking registry. ✔
- Installing dependencies. ✔
- Updating files.
✔ Created 2 files:
- src/components/ui/button.tsx
- src/lib/utils.ts
- Updating src/index.css
✔ Updating src/index.css
Project initialization completed.
自动安装(进 dependencies):@base-ui/react(基元)、cn(cn() 类合并, 4.20 起取代 clsx + tailwind-merge)、class-variance-authority(CVA)、 lucide-react(图标)、@fontsource-variable/geist(字体);另生成根目录 .oxlintrc.json。CLI 已由第 2 节 -D 装好,init 不会重复把它加进依赖。
组件直接落在 src/lib/utils.ts、src/components/ui/button.tsx,无需任何搬移; 收尾验证构建:
5. components.json 逐字段
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova", // 样式族:v4 默认,基于 Base UI
"rsc": false, // React Server Components(Next.js 项目为 true)
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral", // 基础色板
"cssVariables": true, // 全部走 CSS 变量(oklch)
"prefix": ""
},
"iconLibrary": "lucide", // 图标库
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default", // 菜单/侧边栏外观
"menuAccent": "subtle",
"registries": {} // 自定义/extra registry(默认空=用内置 @shadcn)
}
6. 生成的文件结构
init 完成后(别名已映射到 src/)的最终布局:
src/
├── components/ui/ # 复制的组件源码(init 直接生成)
│ ├── button.tsx # init 自带的基础组件
│ └── … # 之后 add 的组件
├── lib/
│ └── utils.ts # cn() 再导出(见下)
└── index.css # init 重写,增补:
@import "tailwindcss";
@import "tw-animate-css";
@import "shadcn/tailwind.css"; # shadcn 主题样式的入口
@import "@fontsource-variable/geist"; # Geist 字体(默认主题字体)
@custom-variant dark (&:is(.dark *)); # dark 变体
@theme inline { … } # 语义色映射(--color-* → --* 变量)
:root { … } # oklch 色板 + --radius 组合(sm…4xl)
.dark { … } # dark 模式色板
(另:根目录 .oxlintrc.json 由 init 生成)
src/lib/utils.ts(init 生成;4.20 起直接再导出 cn 包,不再手写 clsx + tailwind-merge):
7. 启动验证
打开 http://localhost:5173 —— 默认仍是 Vite 欢迎页(init 只把组件源码放进 src/,不改 App.tsx)。展示/使用 Button 与后续 add 组件,见 组件添加与基本使用。生产构建:
8. 参考链接
| 资源 | 链接 |
|---|---|
| shadcn 文档 | https://ui.shadcn.com/docs |
| Vite 安装指南 | https://ui.shadcn.com/docs/installation/vite |
| Base UI | https://base-ui.com/ |
| Tailwind v4 | https://tailwindcss.com/docs |
→ 下一站:组件添加与基本使用
Backlinks (2)
flowchart LR
n0["AI"]
n1["Database"]
n2["Dev Tools"]
n3["Emoji"]
n4["Frontend"]
n5["Game Dev"]
n6["Collection"]
n7["Languages"]
n8["Maps"]
n9["Media"]
n10["Monitor"]
n11["Study Materials"]
n12["Plans"]
n13["Storage"]
n14["对象存储基本用法(Bucket / Object / 常用操作)"]
n15["挂载 Bucket 为本地文件系统(FUSE Mount)"]
n16["对象存储签名 URL(Signed URL)原理与实战"]
n17["对象存储供应商对比(S3 / R2 / OSS / Supabase / MinIO)"]
n18["Prototypes"]
n19["Research"]
n20["Better Auth 源码阅读指南"]
n21["DuckDB 环境与基本使用"]
n22["DuckDB 实战研究"]
n23["DuckDB 模拟数据"]
n24["PostgreSQL 数据用 DuckDB 加速查询"]
n25["HK 角色阅读"]
n26["HK 台词阅读"]
n27["Hollow Knight 英语主题"]
n28["HK 物品阅读"]
n29["HK 地点阅读"]
n30["HK 世界观 / Lore 阅读"]
n31["英语学习 Dashboard"]
n32["English Scraps Archive"]
n33["English Scraps 使用指南"]
n34["Jellyfin 源码阅读指南"]
n35["Lux 资料整理"]
n36["Nest Commander 学习资料"]
n37["NestJS 源码阅读指南"]
n38["Protomaps 自建底图研究"]
n39["自制 PMTiles 地图(最简单例子)"]
n40["MapLibre 集成 Protomaps"]
n41["PMTiles 格式与工具链"]
n42["上海地区底图项目"]
n43["Redash 源码阅读指南"]
n44["Rust 学习计划"]
n45["shadcn/ui 进阶使用"]
n46["shadcn/ui 组件添加与基本使用"]
n47["shadcn/ui 实用研究(从环境到基本使用)"]
n48["shadcn/ui 环境与初始化"]
n49["TRIP 项目核心原理与代码阅读指南"]
n1 --> n22
n1 --> n24
n4 --> n47
n6 --> n0
n6 --> n1
n6 --> n2
n6 --> n3
n6 --> n4
n6 --> n5
n6 --> n7
n6 --> n8
n6 --> n9
n6 --> n10
n6 --> n11
n6 --> n12
n6 --> n13
n6 --> n19
n14 --> n16
n14 --> n17
n14 --> n18
n15 --> n14
n15 --> n16
n15 --> n17
n16 --> n18
n17 --> n14
n17 --> n16
n17 --> n18
n18 --> n14
n18 --> n15
n18 --> n16
n18 --> n17
n18 --> n38
n19 --> n20
n19 --> n22
n19 --> n31
n19 --> n34
n19 --> n35
n19 --> n36
n19 --> n37
n19 --> n38
n19 --> n43
n19 --> n44
n19 --> n47
n19 --> n49
n21 --> n23
n22 --> n1
n22 --> n19
n22 --> n21
n22 --> n23
n22 --> n24
n23 --> n21
n23 --> n24
n24 --> n22
n24 --> n23
n27 --> n25
n27 --> n26
n27 --> n28
n27 --> n29
n27 --> n30
n27 --> n33
n31 --> n27
n31 --> n32
n31 --> n33
n33 --> n31
n33 --> n32
n38 --> n8
n38 --> n39
n38 --> n40
n38 --> n41
n38 --> n42
n39 --> n41
n40 --> n18
n40 --> n42
n41 --> n39
n41 --> n42
n42 --> n40
n42 --> n41
n45 --> n46
n46 --> n45
n46 --> n48
n47 --> n4
n47 --> n19
n47 --> n45
n47 --> n46
n47 --> n48
n48 --> n46
click n0 "../../../../collection/ai/" "AI"
click n1 "../../../../collection/database/" "Database"
click n2 "../../../../collection/dev-tools/" "Dev Tools"
click n3 "../../../../collection/emoji/" "Emoji"
click n4 "../../../../collection/frontend/" "Frontend"
click n5 "../../../../collection/game-dev/" "Game Dev"
click n6 "../../../../collection/" "Collection"
click n7 "../../../../collection/languages/" "Languages"
click n8 "../../../../collection/maps/" "Maps"
click n9 "../../../../collection/media/" "Media"
click n10 "../../../../collection/monitor/" "Monitor"
click n11 "../../../../collection/reading/" "Study Materials"
click n12 "../../../../collection/scraps/plans/" "Plans"
click n13 "../../../../collection/storage/" "Storage"
click n14 "../../../../knowledge/infrastructure/cloud/object-storage/basic-usage/" "对象存储基本用法(Bucket / Object / 常用操作)"
click n15 "../../../../knowledge/infrastructure/cloud/object-storage/mount-bucket/" "挂载 Bucket 为本地文件系统(FUSE Mount)"
click n16 "../../../../knowledge/infrastructure/cloud/object-storage/signed-url/" "对象存储签名 URL(Signed URL)原理与实战"
click n17 "../../../../knowledge/infrastructure/cloud/object-storage/vendors-comparison/" "对象存储供应商对比(S3 / R2 / OSS / Supabase / MinIO)"
click n18 "../../../../prototypes/" "Prototypes"
click n19 "../../../" "Research"
click n20 "../../better-auth/" "Better Auth 源码阅读指南"
click n21 "../../duckdb/basic-usage/" "DuckDB 环境与基本使用"
click n22 "../../duckdb/" "DuckDB 实战研究"
click n23 "../../duckdb/mock-data/" "DuckDB 模拟数据"
click n24 "../../duckdb/postgresql-acceleration/" "PostgreSQL 数据用 DuckDB 加速查询"
click n25 "../../english/hollow-knight/characters/" "HK 角色阅读"
click n26 "../../english/hollow-knight/dialogues/" "HK 台词阅读"
click n27 "../../english/hollow-knight/" "Hollow Knight 英语主题"
click n28 "../../english/hollow-knight/items/" "HK 物品阅读"
click n29 "../../english/hollow-knight/locations/" "HK 地点阅读"
click n30 "../../english/hollow-knight/lore/" "HK 世界观 / Lore 阅读"
click n31 "../../english/" "英语学习 Dashboard"
click n32 "../../english/scraps/archive/" "English Scraps Archive"
click n33 "../../english/scraps/" "English Scraps 使用指南"
click n34 "../../jellyfin/" "Jellyfin 源码阅读指南"
click n35 "../../lux/" "Lux 资料整理"
click n36 "../../nest-commander/" "Nest Commander 学习资料"
click n37 "../../nestjs/" "NestJS 源码阅读指南"
click n38 "../../protomaps/" "Protomaps 自建底图研究"
click n39 "../../protomaps/make-own-map/" "自制 PMTiles 地图(最简单例子)"
click n40 "../../protomaps/maplibre/" "MapLibre 集成 Protomaps"
click n41 "../../protomaps/pmtiles/" "PMTiles 格式与工具链"
click n42 "../../protomaps/shanghai-map/" "上海地区底图项目"
click n43 "../../redash/" "Redash 源码阅读指南"
click n44 "../../rust/" "Rust 学习计划"
click n45 "../advanced/" "shadcn/ui 进阶使用"
click n46 "../components/" "shadcn/ui 组件添加与基本使用"
click n47 "../" "shadcn/ui 实用研究(从环境到基本使用)"
click n48 "./" "shadcn/ui 环境与初始化"
click n49 "../../trip/" "TRIP 项目核心原理与代码阅读指南"