【前端】从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI-第二章《快速开始:使用 Vite + TypeScript 初始化项目》

【前端】从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI-第二章《快速开始:使用 Vite + TypeScript 初始化项目》

从零开始搭建现代前端框架:React 19、Vite、Tailwind CSS、ShadCN UI、Zustand 完整实战教程

第 2 章:快速开始 — 使用 Vite + TypeScript 初始化项目

在上一章中,我们明确了项目目标、技术栈与未来的总体架构路线。本章将正式开始动手,从零初始化一个 基于 React 19 + TypeScript + Vite 的开发环境。

本章你将完成:

  • 创建项目目录
  • 初始化 Vite 项目(React + TS 模板)
  • 安装所有必要依赖
  • 配置基础开发环境(ESLint / Prettier / Tailwind 前置)
  • 解析 package.json 结构,理解项目运行机制

完成本章后,你将拥有一个可以运行、可开发的项目基础结构,为后续多语言、主题、路由、权限等模块打下坚实基础。


2.1 创建项目目录

https://vite.dev/guide/#scaffolding-your-first-vite-project

在任意目录执行:

pnpm create vite@latest

修改Project name,改为web-app,回车:

选择框架,这里我们选择React

选择variant,这里我们选择TypeScript

或者直接使用以下命令,指定使用react-ts

pnpm create vite@latest web-app --template react-ts 

rolldown-vite 是将 Rolldown(一款兼容 Rollup 的 Rust 编写打包工具)集成到 Vite 的实验性方案,目标是用性能更优的 Rust 实现替代 Vite 默认的 Rollup 打包器。

这里选择No

Install with pnpm and start now?

这里选择Yes时,将会自动执行以下命令

cd web-app pnpm install pnpm dev

选择No,需要手动执行以下命令

接着:

cd web-app pnpm install 

完成后文件结构如下:

这是最基础的 React + TypeScript + Vite 项目。


2.2 运行项目,确认环境无误

执行:

pnpm dev 

你将看到:

打开浏览器确认项目运行无误。


2.3 安装项目所需的全部依赖

我们项目使用了丰富但结构清晰的技术栈。下面按照模块安装必要依赖。


2.3.1 安装 UI & 样式相关依赖

安装配置参考:

https://ui.shadcn.com/docs/installation/vite

https://v3.tailwindcss.com/docs/guides/vite

安装 Tailwind CSS v3

pnpm add -D tailwindcss@3 postcss autoprefixer

本教程 刻意选择 Tailwind CSS v3,原因如下:

  • shadcn/ui 官方稳定支持 v3
  • eslint / prettier / tailwind 插件生态成熟
  • 社区资料最完整,适合长期维护型项目
  • 避免 Tailwind v4 当前的实验性不稳定因素

初始化 Tailwind CSS

npx tailwindcss init -p

会生成tailwind.config.js 和 postcss.config.js 两个文件

tailwind.config.js

/** @type {import('tailwindcss').Config} */ export default { content: [], theme: { extend: {}, }, plugins: [], } 

postcss.config.js

export default { plugins: { tailwindcss: {}, autoprefixer: {}, }, } 

将tailwind.config.js修改为

/** @type {import('tailwindcss').Config} */ export default { content: [ "./index.html", "./src/**/*.{js,ts,jsx,tsx}", ], darkMode: "class", theme: { extend: {}, }, plugins: [], }
字段作用
contentTailwind 扫描范围
darkMode使用 class 切换,兼容 next-themes
extend注册 Token(颜色、圆角、字体等)

将 Tailwind 指令添加到 CSS 中

清空./src/index.css中的内容,将 Tailwind 的每个layer的 @tailwind 指令添加到 ./src/index.css 文件中:

@tailwind base; @tailwind components; @tailwind utilities;

启动项目

pnpm run dev

修改App.jsx,添加

 <h1 className="text-3xl font-bold underline"> Hello world! </h1>

查看效果

配置 TypeScript 路径别名

编辑 tsconfig.json 文件

当前版本的 Vite 将 TypeScript 配置拆分成三个文件,其中有两个需要修改。
你需要在 tsconfig.jsontsconfig.app.jsoncompilerOptions 中添加 baseUrlpaths 属性:

修改前:

{ "files": [], "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ] } 

修改后:

{ "files": [], "references": [ { "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" } ], /* 添加代码到此处 */ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }
编辑 tsconfig.app.json 文件

tsconfig.app.json 文件中加入以下代码,以便 IDE 能正确解析路径:

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

修改后

{ "compilerOptions": { "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", "target": "ES2022", "useDefineForClassFields": true, "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", "types": ["vite/client"], "skipLibCheck": true, /* 添加代码到此处 */ "baseUrl": ".", "paths": { "@/*": [ "./src/*" ] }, /* Bundler mode */ "moduleResolution": "bundler", "allowImportingTsExtensions": true, "verbatimModuleSyntax": true, "moduleDetection": "force", "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "erasableSyntaxOnly": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, "include": ["src"] } 
更新 vite.config.ts

安装@types/node

@types/nodeNode.js 的 TypeScript 类型定义文件,只要你使用 Node.js API,就必须安装

例如:

  • process.env
  • __dirname, __filename
  • path, fs, crypto 等 Node 内置模块
  • ESM 中使用 import.meta
  • Vite 配置文件(vite.config.ts)
  • Tailwind 配置文件(tailwind.config.ts)
  • tsconfig 路径解析
  • node 相关脚本

如果没有安装,你会看到 TypeScript 报错

Cannot find name 'process' Cannot find module 'path' Cannot find name '__dirname' 

安装它的目的就是:

让你的 TypeScript 项目在写 Node 相关代码时,获得完整的类型提示、智能补全、类型检查支持。

执行以下命令:

pnpm add -D @types/node

执行结果

vite.config.ts 文件中加入以下代码,使你的应用能够正确解析路径,避免报错:

修改前:

import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' // https://vite.dev/config/ export default defineConfig({ plugins: [react()], }) 

修改后:

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

shadcn/ui 工具

运行 CLI

执行 shadcn init 命令来初始化你的项目配置:

在初始化时,CLI 会询问你一些问题,用于生成 components.json

我们稍后会使用它生成高质量 UI 组件:

pnpm dlx shadcn@latest init

具体的color的效果,请参考https://ui.shadcn.com/colors,我们这里默认选择Netural,回车。

执行成功,我们看到添加了一个components.json文件:

{ "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": false, "tsx": true, "tailwind": { "config": "tailwind.config.js", "css": "src/index.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "iconLibrary": "lucide", "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": {} } 

一个\src\lib\utils.ts文件:

import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } 

更新了\src\index.css

@tailwind base; @tailwind components; @tailwind utilities; @layer base { :root { --background: 0 0% 100%; --foreground: 0 0% 3.9%; --card: 0 0% 100%; --card-foreground: 0 0% 3.9%; --popover: 0 0% 100%; --popover-foreground: 0 0% 3.9%; --primary: 0 0% 9%; --primary-foreground: 0 0% 98%; --secondary: 0 0% 96.1%; --secondary-foreground: 0 0% 9%; --muted: 0 0% 96.1%; --muted-foreground: 0 0% 45.1%; --accent: 0 0% 96.1%; --accent-foreground: 0 0% 9%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 0 0% 98%; --border: 0 0% 89.8%; --input: 0 0% 89.8%; --ring: 0 0% 3.9%; --chart-1: 12 76% 61%; --chart-2: 173 58% 39%; --chart-3: 197 37% 24%; --chart-4: 43 74% 66%; --chart-5: 27 87% 67%; --radius: 0.5rem; } .dark { --background: 0 0% 3.9%; --foreground: 0 0% 98%; --card: 0 0% 3.9%; --card-foreground: 0 0% 98%; --popover: 0 0% 3.9%; --popover-foreground: 0 0% 98%; --primary: 0 0% 98%; --primary-foreground: 0 0% 9%; --secondary: 0 0% 14.9%; --secondary-foreground: 0 0% 98%; --muted: 0 0% 14.9%; --muted-foreground: 0 0% 63.9%; --accent: 0 0% 14.9%; --accent-foreground: 0 0% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 0 0% 98%; --border: 0 0% 14.9%; --input: 0 0% 14.9%; --ring: 0 0% 83.1%; --chart-1: 220 70% 50%; --chart-2: 160 60% 45%; --chart-3: 30 80% 55%; --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; } } @layer base { * { @apply border-border; } body { @apply bg-background text-foreground; } } 

添加组件

你现在可以开始往项目中添加组件了。

pnpm dlx shadcn@latest add button

上面的命令会把 Button(按钮)组件 添加到你的项目中。


你可以像下面这样引入它:

import { Button } from "@/components/ui/button" function App() { return ( <div className="flex min-h-svh flex-col items-center justify-center"> <Button>Click me</Button> </div> ) } export default App

安装 lucide-react(图标库)

lucide-react 是 shadcn/ui 官方推荐的 SVG 图标库,具有以下特点:

  • Tree-shaking 友好,按需引入
  • TypeScript 原生支持
  • 与 Tailwind / shadcn/ui 完美配合
  • 无额外运行时依赖
1️⃣ 安装依赖
pnpm add lucide-react 

2️⃣ 基本使用示例

在任意组件中直接按需引入图标即可:

import { Search, User, Settings } from "lucide-react" function IconDemo() { return ( <div className="flex items-center gap-4"> <Search className="h-5 w-5 text-muted-foreground" /> <User className="h-5 w-5 text-blue-500" /> <Settings className="h-5 w-5 text-green-500" /> </div> ) } 

本质说明

  • 每一个图标都是一个 React 组件
  • className 直接控制大小与颜色
  • h-* w-* 来自 Tailwind

3️⃣ 在 shadcn/ui 组件中使用(推荐)

例如在 Button 中使用图标:

import { Plus } from "lucide-react" import { Button } from "@/components/ui/button" function CreateButton() { return ( <Button> <Plus className="mr-2 h-4 w-4" /> 新建 </Button> ) } 

这是 shadcn 官方示例风格,非常推荐在你的教程中强调。


4️⃣ 图标大小与颜色规范(最佳实践)
用途推荐尺寸
按钮内图标h-4 w-4
普通功能图标h-5 w-5
列表 / 菜单h-4 w-4
图标按钮h-5 w-5h-6 w-6

颜色统一通过 Tailwind 控制:

<Icon className="text-muted-foreground" /> <Icon className="text-primary" /> 

5️⃣ 为什么选择 lucide-react

本项目选择 lucide-react 作为唯一图标库,原因是:shadcn/ui 默认使用 lucideAPI 简单,学习成本极低图标风格统一,适合中后台 / 管理系统不依赖 SVG loader 或额外构建配置

6️⃣ 与 shadcn 初始化配置的关系

在你前面 components.json 中已经有:

"iconLibrary": "lucide" 

这表示:

  • shadcn 生成的组件 默认假设你使用 lucide-react
  • 安装 lucide-react 是必须步骤
  • 不需要额外配置 Vite / SVG 插件

2.3.2 安装国际化 i18n

pnpm add react-i18next i18next i18next-browser-languagedetector

2.3.3 安装主题切换

pnpm add next-themes

2.3.4 安装数据请求层(ky)

pnpm add ky

2.3.5 安装状态管理(Zustand)

pnpm add zustand

2.3.6 安装后端数据管理(TanStack Query)

pnpm add @tanstack/react-query

2.3.7 安装路由(React Router v7)

pnpm add react-router-dom

2.3.8 安装表单(react-hook-form + zod)

pnpm add react-hook-form zod pnpm add @hookform/resolvers 

2.3.9 安装 Toast(sonner)

pnpm add sonner

2.3.10 安装 mock(mockjs)

pnpm add mockjs

2.3.11 安装 Recharts 图表组件

pnpm add recharts

    2.3.13 SVG 处理插件(可选)

    如果你想像 shadcn 那样使用 svg 组件:

    pnpm add -D vite-plugin-svgr

    我们会在 vite.config.ts 中配置它。


    至此,所有核心依赖已经安装完毕。

    接下来,我们需要理解 package.json 的结构。


    2.4 理解 package.json(本项目的依赖结构解析)

    下面是当前项目核心依赖的结构化说明:

    ✔ React & Vite

    "react": "^19.2.0", "react-dom": "^19.2.0", "vite": "^7.2.4", "@vitejs/plugin-react": "^5.1.1", 

    用途:基础框架 + 构建工具


    ✔ TypeScript

    "typescript": "~5.9.3"

    用途:整个项目的类型安全与工程能力基座


    ✔ UI & 样式系统

    "tailwindcss": "^3.4.19", "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", "postcss": "^8.5.6", "autoprefixer": "^10.4.23", "lucide-react": "^0.561.0",

    shadcn + CVA + Tailwind = 通用组件体系的三角组合。


    ✔ 状态与数据请求

    "zustand": "^5.0.9" "ky": "^1.14.1", "@tanstack/react-query": "^5.90.12", 

    ✔ 国际化

    "i18next": "^25.7.2", "i18next-browser-languagedetector": "^8.2.0", "react-i18next": "^16.4.1", 

    ✔ 路由

    "react-router-dom": "^7.10.1", 

    支持最新的 Data APIs、Suspense、Lazy routes


    ✔ 表单 + 校验

    "react-hook-form": "^7.68.0", "zod": "^4.1.13", "@hookform/resolvers": "^5.2.2",

    ✔ Mock

    "mockjs": "^1.1.0"

    ✔ 通知组件(Toast)

    "sonner": "^2.0.7",

    ✔ 图表

    "recharts": "^3.5.1",

    整体结构非常清晰:

    • 依赖结构有明确边界
    • 业务逻辑与 UI 逻辑分离
    • 每个模块都有清晰职责

    2.5 配置 Vite(基础版本)

    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"), }, }, })

    更新为:

    import path from "path" import react from "@vitejs/plugin-react" import svgr from 'vite-plugin-svgr'; // 如果你使用 SVG 组件 import { defineConfig } from "vite" // https://vite.dev/config/ export default defineConfig({ plugins: [react(), svgr()], resolve: { alias: { "@": path.resolve(__dirname, "./src"), }, }, server: { port: 5173, }, })

    2.6 清理默认模板

    默认 App.tsx 内容过于简单,我们先清空:

    import { useState } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' function App() { const [count, setCount] = useState(0) return ( <> <div> <a href="https://vite.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1>Vite + React</h1> <div className="card"> <button onClick={() => setCount((count) => count + 1)}> count is {count} </button> <p> Edit <code>src/App.tsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> ) } export default App 

    修改 src/App.tsx

    import { Button } from "@/components/ui/button" import { Search, User, Settings, Plus } from "lucide-react" function App() { return ( <div className="flex min-h-screen flex-col items-center justify-center p-4 space-x-3 gap-4"> <div>App Initialized</div> <Button>默认按钮</Button> <Button size="sm">小</Button> <Button size="lg">大</Button> <Button variant="outline">描边按钮</Button> <IconDemo /> <CreateButton /> </div> ) } function IconDemo() { return ( <div className="flex items-center gap-4"> <Search className="h-5 w-5 text-muted-foreground" /> <User className="h-5 w-5 text-blue-500" /> <Settings className="h-5 w-5 text-green-500" /> </div> ) } function CreateButton() { return ( <Button> <Plus className="mr-2 h-4 w-4" /> 新建 </Button> ) } export default App

    下一章会替换为真实结构。


    2.7 本章小结

    本章完成了:

    ✔ 初始化 Vite + React + TypeScript 项目
    ✔ 安装所有框架核心依赖
    ✔ 解析 package.json
    ✔ 配置基础 Vite 环境
    ✔ 清理默认模板

    Read more

    AI的提示词专栏:“Meta-Prompt”让模型自己生成 Prompt

    AI的提示词专栏:“Meta-Prompt”让模型自己生成 Prompt

    AI的提示词专栏:“Meta-Prompt”让模型自己生成 Prompt 本文围绕 Meta-Prompt 展开全面解析,先明确其是 “指导模型生成 Prompt 的 Prompt”,实现从 “人设计 Prompt” 到 “模型生成 Prompt” 的跨越,接着阐述其降低设计门槛、提升一致性、优化复杂任务 Prompt、适配动态场景的核心价值。随后详解其 “目标任务定义、输出约束、示例引导、优化方向” 四大核心构成要素,通过教育、职场、技术三大场景提供实战示例与设计思路,还分析了任务定义模糊、输出约束不足等常见问题及解决方案,介绍参数化设计、多轮迭代、领域知识注入等进阶技巧,最后总结其价值并给出从简单场景入手、重视示例等实践建议,助力用户高效设计高质量 Prompt。 人工智能专栏介绍     人工智能学习合集专栏是 AI 学习者的实用工具。它像一个全面的 AI 知识库,把提示词设计、

    网络安全:零暴露公网IP访问本地AI服务的一些方法分享,保障数据隐私!

    网络安全:零暴露公网IP访问本地AI服务的一些方法分享,保障数据隐私!

    如果我们选择本地部署AI模型(如LLaMA、Stable Diffusion)的核心动机之一是对数据隐私的绝对控制! 但当我们需要从外部网络访问这些服务时,就面临两难选择:要么牺牲便利性(只能在内网使用),要么牺牲安全性(将服务暴露至公网)。我这边介绍一种折中的解决方案,实现无需公网IP、零端口暴露的远程安全访问。 公网暴露的潜在威胁 将本地服务的端口通过路由器映射到公网(Port Forwarding),是常见的“暴力”解决方案。但这带来了显著风险: 1. 端口扫描与暴力破解:你的服务IP和端口会暴露在互联网的自动化扫描工具下,可能遭遇持续的登录尝试或漏洞利用攻击。 2. 服务漏洞利用:如果AI服务的Web界面或API存在未修复的漏洞,攻击者可以直接利用。 3. 家庭网络边界被突破:一旦攻击者通过该服务入侵成功,可能进一步渗透到家庭网络中的其他设备。 怎么解决:基于加密隧道的网络隐身 思路是:不让本地服务在公网“露面”,而是让外部访问者通过一条加密的“专属通道”直接进入内网。这可以通过基于零信任网络的P2P VPN工具实现。 具体实现:以Tailscale/Z

    深度解析 MySQL 与 MCP 集成:从环境构建到 AI 驱动的数据交互全流程

    深度解析 MySQL 与 MCP 集成:从环境构建到 AI 驱动的数据交互全流程

    前言 在当前大语言模型(LLM)应用开发的浪潮中,MCP(Model Context Protocol)协议正在成为连接 AI 模型与本地数据设施的关键桥梁。本文将以 MySQL 数据库为例,详细拆解如何通过 MCP 协议让 AI 模型直接操作关系型数据库,涵盖从服务器发现、数据库架构设计、数据初始化、MCP 配置文件编写到复杂自然语言查询与写入的全过程。 第一部分:MCP 服务器的发现与配置获取 在进行任何数据交互之前,首要任务是确立连接协议与服务源。通过蓝耘 MCP 广场,开发者可以快速检索并获取所需的 MCP 服务器配置。 在搜索栏输入 mysql 关键字,系统会立即检索出相关的 MCP 服务器资源。如下图所示,搜索结果中清晰展示了 MySQL 对应的 MCP 服务卡片。 点击选中该 MCP 服务器后,

    Kiro 安装与上手:两种方法快速拥抱AWS新世代AI IDE

    Kiro 安装与上手:两种方法快速拥抱AWS新世代AI IDE

    Kiro是亚马逊 AWS 近期推出的一款备受关注的AI集成开发环境(IDE),它在竞争激烈的AI编码工具市场中,选择了一条差异化的道路。与市面上主流的、强调“即兴发挥”(Vibe Coding)的工具如Cursor不同,Kiro的核心是面向企业和专业开发者的“规范驱动开发”(Spec-Driven Development)。它的目标不仅仅是帮助开发者更快地编写代码,更是希望通过结构化的流程,引导团队产出更健壮、更易于维护的生产级软件。 以下是对Kiro的详细介绍: 📝 核心哲学:从“即兴创作”到“规范驱动” Kiro的诞生源于对当前“即兴编码”潮流的反思。许多AI工具虽然能快速生成代码,但也带来了缺乏文档、逻辑混乱、难以维护的“技术债务”问题 。Kiro的解决方案是在AI生成代码之前,引入一个严谨的规划阶段 。 其核心工作流围绕三个动态的“规范文件”展开,形成了一个“需求-设计-任务”的闭环: * requirements.md (需求):Kiro会将你的自然语言描述(无论是口头禅式的还是正式的)转化为结构化的用户故事和验收标准,通常会使用易于理解的EARS(