Skip to content

7.0 跑通你的第一个全栈应用

本节目标:让 AI 帮你生成一个完整的 CRUD(增删改查)应用,跑起来,验证数据是否正确。

你在第六章拿到了数据库,在序言里理解了 API 的概念。现在把它们串起来——做一个最经典的 Todo 待办事项应用。

全栈数据流:一张图看懂

在动手之前,先理解数据是怎么流动的:

用户点击"添加" → 前端发送请求 → 后端 API 接收 → Drizzle 写入数据库

用户看到新数据 ← 前端渲染响应 ← 后端返回结果 ← 数据库返回确认

这就是全栈应用的核心循环。CRUD 四个操作,每一个都走这条路。

👤
用户
📱
前端
⚙️
API
🗄️
数据库

告诉 AI 创建项目

你不需要手写这些代码。直接告诉 AI:

"帮我创建一个 Todo 应用,使用 Next.js + Drizzle ORM + PostgreSQL。需要完整的 CRUD 功能:添加待办、查看列表、标记完成、删除待办。数据库连接用 .env 里的 DATABASE_URL。"

AI 会帮你生成以下文件结构:

src/
├── db/
│   ├── index.ts          # 数据库连接
│   └── schema.ts         # 表结构定义
├── app/
│   ├── api/todos/
│   │   └── route.ts      # API 路由(处理 CRUD 请求)
│   └── page.tsx           # 前端页面(展示和操作)

检查 AI 的作业

AI 生成了三类文件。你不需要看懂每一行代码,但要知道每个文件的职责——这样出问题时你才知道该让 AI 改哪个文件。

1. 数据库表结构(schema.ts)

这个文件定义了"数据长什么样"——Todo 有哪些字段、每个字段是什么类型。相当于数据库的设计图纸。

好奇的话展开看看,不看也完全没问题
typescript
// src/db/schema.ts
export const todos = pgTable('todos', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  completed: boolean('completed').default(false),
  createdAt: timestamp('created_at').defaultNow(),
})

对照第六章学的知识:id 是主键,title 不能为空,completed 默认是 falsecreatedAt 自动记录创建时间。

2. API 路由(route.ts)

这个文件是"后端接口"——前端发请求到这里,它负责跟数据库交互。POST 对应"增",GET 对应"查",这就是序言里讲的 RESTful 设计。

好奇的话展开看看,不看也完全没问题
typescript
// src/app/api/todos/route.ts

// C - Create(增):添加一条待办
export async function POST(request: Request) {
  const { title } = await request.json()
  const newTodo = await db.insert(todos).values({ title }).returning()
  return Response.json(newTodo[0])
}

// R - Read(查):获取所有待办
export async function GET() {
  const allTodos = await db.select().from(todos).orderBy(todos.createdAt)
  return Response.json(allTodos)
}

3. 前端页面(page.tsx)

这个文件是用户看到的界面——输入框、列表、勾选框、删除按钮。它通过调用上面的 API 来操作数据:

  • 页面加载时,调用 GET /api/todos 获取列表
  • 用户输入标题点"添加",调用 POST /api/todos
  • 用户点勾选框,调用 PATCH /api/todos/[id] 更新状态
  • 用户点删除,调用 DELETE /api/todos/[id]

动手跑起来

现在让它真正跑起来。第一次跑不通是正常的——环境变量没配、表没推送、端口被占用,这些都是新手必经之路。把报错丢给 AI 就行。

第一步:推送表结构到数据库

bash
pnpm drizzle-kit push

这条命令会把你在 schema.ts 里定义的表结构同步到云端数据库。

第二步:启动开发服务器

bash
pnpm dev

打开 http://localhost:3000,你应该能看到一个空的待办列表。

第三步:试试 CRUD

操作你做什么背后发生了什么
添加输入"学习数据库",点添加POST /api/todos → 数据库插入一行
查看页面自动刷新列表GET /api/todos → 数据库查询所有行
完成点击勾选框PATCH /api/todos/1 → 数据库更新 completed 字段
删除点击删除按钮DELETE /api/todos/1 → 数据库删除该行

用 Drizzle Studio 验证

想亲眼看看数据库里发生了什么?

bash
pnpm drizzle-kit studio

打开后你能看到 todos 表里的每一行数据,和你在页面上操作的结果完全对应。

这就是你作为产品负责人的核心技能——不是读代码,而是验证结果。数据库里的数据对不对、API 返回的格式对不对、页面显示的内容对不对。能验证这三件事,你就能放心地让 AI 帮你写后端。

常见问题

Q:添加后列表没更新? 告诉 AI:"添加待办后自动刷新列表,不需要手动刷新页面。"AI 会在 POST 请求成功后重新获取数据。

Q:删除报错 404? 检查 API 路由文件的路径是否正确。Next.js 的动态路由需要 [id] 文件夹:app/api/todos/[id]/route.ts

Q:数据库里没有表? 确认执行了 pnpm drizzle-kit push。如果报错,检查 .env 里的 DATABASE_URL 是否正确。

这个示例教会你什么

你刚才完成的,是一个最小但完整的全栈应用。它包含了:

  • 前端:用户界面、事件处理、API 调用
  • 后端:API 路由、请求处理、数据校验
  • 数据库:表结构、CRUD 操作、数据持久化

以后不管做什么应用——博客、电商、社交——底层逻辑都是这四个字母:CRUD。区别只是表结构更复杂、业务逻辑更多、界面更花哨。


下一步

CRUD 跑通了,你已经体验了全栈数据流。接下来去 一个接口不够用了——当数据量和需求增长时,一个简单的 CRUD 接口该怎么进化。