Skip to content

环境与初始化

本页目的: 把 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 模板还会额外追问两个问题

  1. Which linter to use? —— Oxlint(默认)/ ESLint
  2. Install with pnpm and start now? —— 是否自动装依赖并启动 dev server

全部选项都可用 CLI flag 显式指定(非 TTY / CI 脚本环境会自动免交互):

flag 作用 默认
-t, --template react-ts framework / variant
--eslint / --no-eslint 选 ESLint / Oxlint(仅 React 模板) Oxlint
-i, --immediate / --no-immediate 自动装依赖并起 dev server 不装
--overwrite 目标目录非空时直接覆盖 报错退出
--no-interactive 整体免交互,未指定项全部取默认 非 TTY 自动非交互

实测:默认 linter 为 Oxlintpnpm lintoxlint,零 ESLint 依赖); 加 --eslint 则生成 eslint.config.js + eslint 10 + typescript-eslint, pnpm linteslint .。其余脚手架(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 构建解析 @/*):

"moduleResolution": "bundler",
"paths": { "@/*": ["./src/*"] },

tsconfig.json(根,solution-style) —— 也要加同样的 paths(供 shadcn CLI 解析别名、决定组件落盘位置;只配 tsconfig.app.json 的话,init 会把组件 写到项目根 ./@/ 而不是 src/):

"compilerOptions": {
  "baseUrl": ".",
  "paths": { "@/*": ["./src/*"] }
}

src/index.css —— 至少先有:

@import "tailwindcss";
@import "tw-animate-css";

✅ 完成本节三步后(Tailwind 已装、别名两处配好),init 的 preflight (Tailwind / alias 校验)直接通过,组件按别名写进 src/(见第 4 节)。

4. init 初始化

pnpm shadcn init -d    # 本地 CLI(第 2 节已 -D 装好 4.20.1);-d = --defaults,免交互

实测流程输出(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.tssrc/components/ui/button.tsx,无需任何搬移; 收尾验证构建:

pnpm build

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):

export { cn } from "cn"

7. 启动验证

pnpm dev    # → http://localhost:5173

打开 http://localhost:5173 —— 默认仍是 Vite 欢迎页(init 只把组件源码放进 src/,不改 App.tsx)。展示/使用 Button 与后续 add 组件,见 组件添加与基本使用。生产构建:

pnpm build && pnpm preview    # 预览 → http://localhost:4173

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 项目核心原理与代码阅读指南"
Links (1)