【零基础AI应用开发】第02章:项目初始化与 Next.js 基础(入门篇)

📦 项目教程仓库:https://github.com/ZIQI-a/AI_Agent_study

🚀 成品项目地址:https://github.com/ZIQI-a/huamiao_Agent

本章目标

要做的事:创建话喵项目,理解项目结构,跑起开发服务器

学到的知识

  • Next.js 是什么,为什么选它

  • App Router 的文件路由系统

  • 服务端组件 vs 客户端组件

  • 页面、布局、加载状态的关系

2.1 为什么选 Next.js?

作为前端开发者,你可能用过 React、Vue、Nuxt 等框架。Next.js 有几个关键优势:

复制代码
React:    只负责 UI 渲染,路由、SSR、构建都要自己配
Next.js:  React + 路由 + SSR + API Routes + 构建工具,开箱即用

为什么 AI 应用特别适合 Next.js?
  ✅ 内置 API Routes → 后端 API 不需要额外服务
  ✅ 服务端组件     → API Key 只在服务端,不会泄露到前端
  ✅ 流式响应支持   → AI 的打字机效果天然支持
  ✅ Vercel 部署    → 一键部署,和 AI SDK 同一家公司
  ✅ 全栈 TypeScript → 类型安全,前后端一套语言

2.2 创建项目

bash 复制代码
# 进入你的工作目录
cd /Users/Code/学习练习代码/AGENTS

# 创建 Next.js 项目
pnpm dlx create-next-app@latest huamiao --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"

# 各参数含义:
# --typescript     → 使用 TypeScript
# --tailwind       → 集成 Tailwind CSS
# --eslint         → 代码检查
# --app            → 使用 App Router(不是旧的 Pages Router)
# --src-dir        → 源码放在 src/ 目录下
# --import-alias   → 路径别名 @/ 指向 src/

安装过程中可能问你几个问题,选择默认值即可。

bash 复制代码
# 进入项目目录
cd huamiao

# 启动开发服务器
pnpm dev

打开浏览器访问 http://localhost:3000,你应该能看到 Next.js 的默认欢迎页面。

2.3 项目目录结构

复制代码
huamiao/
├── src/
│   ├── app/                    ← 核心:App Router 目录
│   │   ├── favicon.ico         ← 网站图标
│   │   ├── globals.css         ← 全局样式
│   │   ├── layout.tsx          ← 根布局(所有页面共享)
│   │   └── page.tsx            ← 首页(/ 路由)
│   ├── components/             ← 组件目录(后面创建)
│   └── lib/                    ← 工具函数(后面创建)
├── public/                     ← 静态资源(图片、字体等)
├── next.config.ts              ← Next.js 配置
├── tailwind.config.ts          ← Tailwind 配置
├── tsconfig.json               ← TypeScript 配置
├── package.json                ← 项目依赖
└── pnpm-lock.lock              ← 依赖锁定文件

知识点:node_modules 去哪了?

pnpm 使用全局存储 + 符号链接的方式,node_modules 比 npm 小很多。

依赖的实际文件存在 pnpm 的全局目录中,项目里只是链接。

2.4 App Router 核心概念

App Router 是 Next.js 13+ 引入的新路由系统,用文件夹结构定义路由。

文件即路由

复制代码
src/app/
├── page.tsx              →  /          (首页)
├── about/
│   └── page.tsx          →  /about     (关于页)
├── articles/
│   ├── page.tsx          →  /articles  (文章列表)
│   └── create/
│       └── page.tsx      →  /articles/create(创建文章)
└── poems/
    └── page.tsx          →  /poems     (诗词页)

规则很简单:

  • 文件夹名 = URL 路径段

  • page.tsx = 该路径对应的页面组件

特殊文件名

复制代码
page.tsx       → 页面(用户访问这个 URL 时看到的内容)
layout.tsx     → 布局(包裹子页面,不会随页面切换重新渲染)
loading.tsx    → 加载状态(页面加载时显示的 UI)
error.tsx      → 错误处理(页面出错时显示的 UI)
not-found.tsx  → 404 页面

2.5 布局文件 layout.tsx

打开 src/app/layout.tsx

typescript 复制代码
// 这是根布局,所有页面都会被它包裹
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";

const inter = Inter({ subsets: ["latin"] });

// 页面的元信息(标题、描述)
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

// 根布局组件
// children 是当前页面的内容
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    
      {children}
    
  );
}

布局的作用

复制代码
┌─────────────────────────────────┐
│ layout.tsx                       │
│ ┌─────────────────────────────┐ │
│ │                       │ │
│ │                       │ │
│ │     ┌───────────────────┐   │ │
│ │     │ {children}        │   │ │
│ │     │ (这里是 page.tsx) │   │ │
│ │     │                   │   │ │
│ │     └───────────────────┘   │ │
│ │                      │ │
│ │                      │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────┘

切换页面时,布局不会重新渲染,只有 children 部分会更新。这意味着导航栏、侧边栏等放在布局中是高效的。

2.6 页面文件 page.tsx

打开 src/app/page.tsx

typescript 复制代码
// 这是首页的内容
export default function Home() {
  return (
    
      Hello Next.js!
    
  );
}

现在我们来改成话喵的首页:

typescript 复制代码
export default function Home() {
  return (
    
      话喵
      
AI 智能创作平台

    
  );
}

保存后浏览器会自动刷新(热更新),你会看到页面内容变了。

2.7 服务端组件 vs 客户端组件

这是 App Router 最重要的概念之一。

服务端组件(默认)

typescript 复制代码
// 这是一个服务端组件(默认)
// 它在服务器上渲染,HTML 直接发给浏览器
export default function ServerComponent() {
  return 我在服务器上渲染;
}

特点

  • 在服务器上执行,不在浏览器执行

  • 可以直接访问数据库、文件系统、环境变量

  • 不能用 useState、useEffect 等 React Hooks

  • 不能绑定事件(onClick 等)

客户端组件

typescript 复制代码
"use client";  // ← 加了这行就是客户端组件

import { useState } from "react";

export default function ClientComponent() {
  const [count, setCount] = useState(0);

  return (
     setCount(count + 1)}>
      点击了 {count} 次
    
  );
}

特点

  • 在浏览器上执行

  • 可以用 React Hooks

  • 可以绑定事件

  • 不能直接访问数据库等服务端资源

如何选择?

复制代码
需要交互(点击、输入、动画)?  → "use client"
需要访问数据库/API Key?        → 服务端组件(不加 "use client")
需要展示数据?                  → 服务端组件
需要状态管理?                  → "use client"

简单规则:
  能用服务端组件就用服务端组件
  需要交互时才加 "use client"

知识点:为什么服务端组件是默认?

  • 性能更好:不发送 JS 到浏览器

  • 安全:敏感数据(API Key)不会暴露到前端

  • SEO 友好:HTML 在服务器生成

  • 只有需要交互的部分才变成客户端组件

2.8 创建第一个路由

让我们为话喵创建几个页面。

创建文章创作页面

bash 复制代码
mkdir -p src/app/articles/create

创建 src/app/articles/create/page.tsx

typescript 复制代码
export default function CreateArticle() {
  return (
    
      文章创作
      
输入标题,AI 帮你写文章

    
  );
}

创建古诗词页面

bash 复制代码
mkdir -p src/app/poems

创建 src/app/poems/page.tsx

typescript 复制代码
export default function Poems() {
  return (
    
      古诗词生成
      
输入名词,AI 创作古诗词

    
  );
}

现在访问:

  • http://localhost:3000 → 首页

  • http://localhost:3000/articles/create → 文章创作页

  • http://localhost:3000/poems → 古诗词页

三个页面互相独立,但共享根布局。

2.9 加载状态 loading.tsx

创建 src/app/articles/create/loading.tsx

typescript 复制代码
export default function Loading() {
  return (
    
      
    
  );
}

当文章创作页面加载时(比如等待 API 响应),Next.js 会自动显示这个 loading 组件。用户体验更好。

本章小结

概念 说明
App Router 文件夹结构定义路由
page.tsx 页面组件,对应一个 URL
layout.tsx 布局组件,包裹子页面,不随页面切换重渲染
loading.tsx 加载状态,页面加载时自动显示
服务端组件 默认,在服务器执行,可访问数据库和环境变量
客户端组件 加 "use client",在浏览器执行,可交互

动手验证

  • pnpm dev 启动项目

  • 访问 http://localhost:3000 看到话喵首页

  • 访问 http://localhost:3000/articles/create 看到文章创作页

  • 访问 http://localhost:3000/poems 看到古诗词页

  • 修改某个页面的内容,保存后浏览器自动刷新

下一章预告

我们将引入 Tailwind CSS 和 shadcn/ui 组件库,搭建话喵的整体 UI 布局 ------ 左侧导航栏 + 主内容区,设计猫咪主题的配色方案。


如果这个教程对你有帮助,欢迎 ⭐ Star 支持一下!