全栈项目 学习日记 (第一章)

全栈项目之博客系统 学习日记 (第一章)

前言 🚀

AI Agent 时代的 IT 行业,单会前端或者单会后端已经不足以满足市场需求,"AI + 全栈" 才是程序员的核心竞争力。这个系列我将从前端到后端,一步一个脚印,打造一个功能完备的博客系统 ------ 包含登录功能、文章系统、AIGC 生成功能,后端将采用 NestJS 框架搭建。

作为系列的开篇,我们先聚焦前端基础搭建,用 React + TypeScript + Vite 构建项目骨架,搭配 shadcn/ui 组件库和 Tailwind CSS 样式,再通过 React Router 实现路由管理,为后续功能开发打下坚实基础~

一、初始化 React 项目 🏗️

想要开启前端开发,第一步就是搭建标准的项目结构。按照以下步骤操作,快速初始化一个 React + TypeScript + Vite 项目:

  1. 打开终端,执行初始化命令:npm init vite
  2. 给项目命名为 notes(对应博客系统的核心功能)
  3. 框架选择 React(成熟稳定,生态丰富)
  4. 变体选择 TypeScript(静态类型检查,减少开发 bug)
  5. 后续配置默认选择即可完成初始化

初始化完成后,执行 cd notes 进入项目目录,再通过 pnpm i 安装依赖,最后用 npm run dev 启动项目,就能看到默认的 React 初始页面啦~

如果对 React 的组件思想、Vite 的构建原理或 TypeScript 的类型定义还不熟悉,建议先翻翻我前面的文章补充相关基础知识点,再继续后续开发哦~

二、UI 组件库:shadcn/ui ✨

1. 什么是 shadcn/ui?

shadcn/ui 是一个基于 Tailwind CSS 和 Radix UI 构建的开源 UI 组件库,它不像 Ant Design 那样需要全局引入,而是采用 "按需下载、本地修改" 的模式,组件源码会直接复制到项目中,支持完全自定义样式和逻辑。

2. 为什么选择 shadcn/ui?

  • 严格按需加载:只下载当前页面需要的组件,不会引入冗余代码,有效减少项目体积
  • 可定制性强:组件源码本地化,支持根据需求修改样式、逻辑,适配各种设计风格
  • 与 Tailwind CSS 深度融合:无需额外编写大量样式,直接通过 Tailwind 工具类扩展样式
  • 类型安全:完全支持 TypeScript,每个组件都有完善的类型定义,开发体验更流畅

3. 安装 shadcn/ui

执行命令:pnpm i shadcn@latest安装完成后,打开 package.json 文件,就能看到 shadcn 的版本号(本项目使用 3.7.0 版本),表示组件库已成功引入项目。

三、配置 Tailwind CSS 🎨

shadcn/ui 本身基于 Tailwind CSS 构建,必须先配置好 Tailwind,才能解锁 shadcn 的完整功能。而且 shadcn 的初始化命令会校验 Tailwind 配置,未配置或配置不规范会直接终止执行,所以这一步至关重要~

配置步骤:

  1. 安装依赖:执行 npm install tailwindcss @tailwindcss/vite,同时安装 Tailwind 核心包和 Vite 插件
  2. 配置 Vite:在 vite.config.ts 中引入 Tailwind 插件,确保样式能被正确解析(后续会详细说明 Vite 完整配置)
  1. 引入样式:在 src/index.css 清空所有样式再添加 @import 'tailwindcss';,加载 Tailwind 基础样式
  1. 清理冗余文件:清空默认生成的 app.css,避免样式冲突
  2. 适配布局:在 App.tsx 中添加弹性布局相关样式,确保页面结构自适应

四、配置 Vite:路径别名与类型声明 🛠️

Vite 作为现代化构建工具,配置路径别名能让模块导入更简洁,提升开发效率。具体配置如下:

1. 核心配置:路径别名

打开 vite.config.ts,添加 resolve.alias 配置,将 @ 映射到 src 目录:

typescript

复制代码
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import path from 'path' // Node.js 内置模块,用于处理文件路径

export default defineConfig({
  plugins: [react(), tailwindcss()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'), // __dirname 表示当前文件所在目录
    }
  }
})

这样一来,我们导入组件时就可以用 @/components/Button 替代 ../../components/Button,路径更简洁,维护更方便~

2. Node 类型声明

由于我们使用了 Node.js 的 path 模块,TypeScript 会缺少类型声明,导致编译报错。需要单独安装类型声明文件:

  • 执行命令:pnpm i -D @types/node-D 表示开发依赖,只在开发环境生效)

3. 避坑指南:安装错误处理

如果不小心输错命令(比如少写 typess),会导致类型声明缺失,项目爆红。此时需要按以下步骤修复:

  1. Remove-Item -Recurse -Force node_modules, pnpm-lock.yaml:删除 node_modules 和锁文件(Windows 系统)
  2. pnpm i:重新安装所有依赖
  3. pnpm i -D @types/node:正确安装 Node 类型声明文件

五、TS 配置文件:目录输出建议 📝

为了获得目录输出建议能力以提升我们的项目开发效率,并适配 Vite 中配置的路径别名(@ -> src),需要在 TypeScript 配置文件中同步配置 baseUrlpaths,确保 TypeScript 能正确识别路径别名,避免类型校验报错。

配置方式

tsconfig.json 文件的 "compilerOptions" 配置块中添加以下内容:

json

复制代码
{
  "compilerOptions": {
    // 保留原有其他配置项...
    "baseUrl": ".",
    "paths": {
      "@/*": [
        "src/*"
      ]
    }
  }
}
  • baseUrl: 设定模块解析的基础目录为项目根目录(.),TypeScript 会基于该目录解析非相对路径的模块。
  • paths: 配置路径映射规则,将 @/* 映射到 src/*,与 Vite 中的别名配置保持一致,保证在 TS 代码中使用 @/xxx 形式引入文件时,类型检查和代码提示功能正常工作。
  • 需要注意的是:该配置必须和 Vite 的别名配置配合使用,否则会出现「TS 类型提示正常,但运行 / 打包报错」的问题。

配置完后,我们来到app.tsx。观察下面图片,src目录下的目录或文件会被提示出来供我们选择,理解目录输出建议带来的效果:

六、初始化 shadcn/ui:按需加载组件 📦

配置完 Tailwind CSS、Vite 别名和 TS 路径后,才能初始化 shadcn/ui------ 因为 shadcn 的 CLI 会依赖这些配置,确定组件的安装路径和代码规范。

1. 执行初始化命令

在终端输入:npx shadcn@latest init,执行后会出现交互配置:

  • 选择样式风格:默认选择 Neutral 主题(简洁百搭,适合博客系统)
  • 其他配置保持默认

2. 初始化后生成的核心文件

  • components.json:项目根目录下的核心配置文件,记录 shadcn 的基础配置(组件路径、主题风格、是否支持 TS 等),后续添加组件时会自动更新,无需手动修改
  • src/components/ 目录:包含通用组件和 UI 组件子目录,所有下载的 shadcn 组件都会放在 src/components/ui/
  • src/lib/ 目录:存放 shadcn 依赖的工具函数(如 cn 函数,用于合并 Tailwind 类名)

3. 按需添加组件:以 Button 为例

shadcn 的核心优势是按需加载,我们以常用的 Button 组件为例,演示如何添加和使用:

  1. 执行命令:npx shadcn@latest add button

  2. CLI 会自动完成以下操作:

    • 将 Button 组件源码复制到 src/components/ui/button.tsx
    • 自动引入 cn 工具函数,处理样式合并
    • 更新 components.json,记录已添加的 Button 组件
  3. App.tsx 中使用组件:

tsx

复制代码
import { Button } from '@/components/ui/button';

function App() {
  return (
    <>
      <Button variant='default'>金手指</Button>
      <Button variant='destructive'>银手指</Button>
    </>
  );
}

运行项目后,就能看到两个不同样式的按钮 ------variant='default' 对应默认样式,variant='destructive' 对应危险操作样式(红色),直接开箱即用,无需额外编写样式~

4. 小知识:npx 是什么?

npx 是 Node.js 自带的工具,核心作用是 "临时安装并执行 npm 包中的命令",无需全局或本地预先安装包。比如执行 npx shadcn@latest add button 时,npx 会临时下载 shadcn 包,执行添加组件的命令,完成后自动删除包,不会占用项目依赖资源,特别适合试用工具或执行一次性命令~

七、前端路由配置:接管页面跳转 🚦

前端路由是单页应用(SPA)的核心,负责管理页面跳转和组件渲染。本项目使用 React Router v7 实现路由功能,让所有页面通过路由加载。

1. 目录规划

新建 src/router 目录,所有路由配置都放在这里,在目录下新建 index.tsx,集中管理路由规则。

2. 安装依赖

执行命令:pnpm i react-router-dom(本项目使用 7.13.0 版本)React Router DOM 是专门用于浏览器环境的路由库,提供了路由管理、导航、参数传递等核心功能,是 React 项目实现页面跳转的首选方案。

3. 导入核心路由组件

router/index.tsx 中导入以下核心组件:

tsx

复制代码
import {
  BrowserRouter as Router, // 浏览器路由根组件,包裹所有路由配置
  Routes, // 路由容器,管理所有 Route 子组件
  Route // 单个路由规则,映射路径与组件
} from 'react-router-dom';
  • BrowserRouter:基于 HTML5 的 History API 实现,URL 格式更美观(如 /mine 而非 /#/mine
  • Routes:路由规则容器,只能包含 Route 组件,会自动匹配当前 URL 对应的 Route
  • Route:定义单个路由,通过 path 指定 URL 路径,element 指定对应的组件

4. 路由懒加载:优化性能 🚀

(1)什么是路由懒加载?

路由懒加载是指 "只有当用户访问某个路由时,才加载对应的组件代码",而不是在项目初始化时一次性加载所有组件。

(2)为什么需要路由懒加载?

如果项目页面较多,一次性加载所有组件会导致初始打包体积过大,页面加载速度变慢,影响用户体验。懒加载能拆分代码包,减小初始加载体积,提升首屏加载速度。

(3)实现路由懒加载

通过 React 内置的 Suspense 组件和 lazy 函数实现:

tsx

复制代码
import { Suspense, lazy } from 'react'; // 导入懒加载核心工具

// 懒加载页面组件,只有访问对应路由时才加载
const Home = lazy(() => import('@/pages/Home'));
const Mine = lazy(() => import('@/pages/Mine'));
  • lazy 函数:接收一个函数,该函数动态导入组件,返回一个 Promise
  • Suspense 组件:包裹懒加载的路由,当组件正在加载时,显示 fallback 中的占位内容

5. 自定义 Loading 组件:提升用户体验 ⏳

为了让用户在组件加载时不感到无聊,我们可以自定义一个 Loading 动画作为占位:

  1. 新建 src/components/Loading 目录,创建 index.tsxloading.module.css 文件

  2. 编写 Loading 组件(使用模块化 CSS 避免样式污染):

    • loading.module.css(定义双球旋转动画):

    css

    复制代码
    .wrapper>div {
      position: fixed;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      margin: auto;
      width: 60px;
      height: 60px;
      opacity: 0.6;
      border-radius: 50%;
      background-color: #d44439;
      animation: loading 1.4s infinite ease-in-out;
    }
    .wrapper>div:nth-child(2) {
      animation-delay: -0.7s; /* 第二个球延迟动画,形成交替效果 */
    }
    @keyframes loading {
      0%, 100% { transform: scale(0.0); }
      50% { transform: scale(1.0); }
    }
    • index.tsx(组件结构):

    tsx

    复制代码
    import styles from './loading.module.css';
    
    export default function Loading() {
      return (
        <div className={styles.wrapper}>
          <div></div>
          <div></div>
        </div>
      );
    }
  3. 在路由配置中使用:

tsx

复制代码
<Suspense fallback={<Loading />}>
  <Routes>
    {/* 路由规则 */}
  </Routes>
</Suspense>

这样,当组件加载时,页面会显示两个交替缩放的红色小球,让等待过程更友好~

这里只需要观察动画效果,首页与我的 页面实现在这个系列的后面文章我会一一讲解。

八、面试官会问 ❓

  1. **shadcn/ui 和 Ant Design 的区别是什么?**答:① 引入方式:shadcn 按需下载源码到本地,Ant Design 需全局或按需引入依赖包;② 可定制性:shadcn 支持修改组件源码,Ant Design 定制样式需通过主题配置或覆盖样式;③ 体积:shadcn 只包含所需组件,体积更小;Ant Design 即使按需引入也会有基础依赖体积;④ 技术依赖:shadcn 基于 Tailwind CSS,Ant Design 有自研样式系统。
  2. **路由懒加载的实现原理是什么?**答:基于 ES6 的 import() 动态导入语法,React.lazy 接收一个返回 Promise 的函数,当路由被访问时,才执行动态导入加载组件代码。Suspense 组件监听 Promise 状态,加载完成前显示 fallback 占位内容,加载成功后渲染组件。
  3. **为什么要使用模块化 CSS?**答:① 避免样式污染:模块化 CSS 会为类名添加唯一哈希值(如 .loading_wrapper_123),不同组件的同名类不会冲突;② 提高可维护性:样式与组件绑定,便于后续修改和删除,不会影响其他组件;③ 支持 TypeScript 类型提示,减少样式类名拼写错误。
  4. **Vite 配置路径别名的作用是什么?**答:① 简化导入路径:用 @/components/Button 替代 ../../components/Button,避免层级过深导致的路径混乱;② 提高项目可维护性:如果目录结构调整,只需修改别名配置,无需逐个修改文件中的导入语句。
  5. **Tailwind CSS 的优势是什么?**答:① 原子化样式:提供大量预定义工具类(如 flexbg-gray-50),无需编写自定义 CSS;② 响应式设计:内置响应式前缀(如 md:flex),轻松实现多端适配;③ 样式复用:通过 @apply 合并常用样式,减少重复代码;④ 与 shadcn/ui 深度融合,无需额外适配。

九、结语 🌟

至此,博客系统的前端基础框架已经搭建一部分了!我们通过 React + TypeScript + Vite 构建了项目骨架,用 shadcn/ui 和 Tailwind CSS 实现了组件化开发和样式美化,通过 React Router 实现了路由管理、懒加载,为后续功能开发铺平了道路。

接下来,我们将聚焦前端功能开发,实现首页、登录页面等核心界面。如果在搭建过程中遇到问题,欢迎在评论区交流~ 让我们一起朝着 "全栈工程师" 的目标稳步前进!

相关推荐
0思必得02 小时前
[Web自动化] 数据抓取、解析与存储
运维·前端·爬虫·selenium·自动化·web自动化
chen_song_2 小时前
Agent 经典范式构建之 ReAct (Reasoning and Acting): 一种将“思考”和“行动”紧密结合的范式,让智能体边想边做,动态调整
前端·react.js·前端框架
想起你的日子2 小时前
CSS3 弹性盒子(Flex Box)
前端·css3
园小异2 小时前
2026年浏览器革命:Chrome Edge 人工智能版完全指南
前端·chrome
萧曵 丶2 小时前
CSS3 业务开发高频样式
前端·css·css3
夏幻灵2 小时前
HTML中路径符号.和/详解
前端·html
花归去2 小时前
Vue Router 的导航守卫
开发语言·前端·javascript
json{shen:"jing"}2 小时前
16_Vue引入路由配置 17.路由传递参数
前端·javascript·vue.js
机器视觉的发动机2 小时前
大语言模型:从理论起源到技术革命
前端·javascript·自动化·视觉检测·ecmascript·easyui·机器视觉