Next.js 全栈初体验 —— 用 Prisma + SQLite 搭建计数器

前言

Next.js 不仅是一个前端框架,更是一个提供 全栈开发能力 的平台。借助 App Router + API Routes + 数据库集成,我们可以轻松实现既有前端交互,又有后端逻辑的数据驱动应用。

本文将带你实现一个 全栈计数器应用,涵盖:

  • Prisma + SQLite 数据库初始化
  • API Routes 数据接口
  • 前端页面调用 API
  • 数据在前后端的流转过程

项目初始化

首先创建项目:

lua 复制代码
npx create-next-app@latest next-counter-app
cd next-counter-app

安装 Prisma 及客户端:

bash 复制代码
npm install prisma @prisma/client

初始化 Prisma 配置:

csharp 复制代码
npx prisma init --datasource-provider sqlite

执行后你会看到项目根目录生成了 prisma/schema.prisma 文件,以及 .env 配置文件。


定义数据库模型

打开 prisma/schema.prisma,定义一个简单的 Counter 模型:

kotlin 复制代码
model Counter {
  id     Int    @id @default(autoincrement())
  value  Int    @default(0)
}

保存后执行数据库迁移:

csharp 复制代码
npx prisma migrate dev --name init

这一步会在项目下生成 dev.db 文件(SQLite 数据库),并在里面创建 Counter 表。


配置 Prisma 客户端

新建 lib/prisma.ts,用于创建数据库客户端实例:

typescript 复制代码
import { PrismaClient } from '@prisma/client'

const globalForPrisma = global as unknown as { prisma: PrismaClient }

export const prisma =
  globalForPrisma.prisma || new PrismaClient({ log: ['query'] })

if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

export default prisma

这样能避免开发模式下的热重载导致多个数据库连接。


编写 API Routes

app/api/counter/route.ts 中添加接口逻辑:

php 复制代码
import { NextResponse } from 'next/server'
import prisma from '@/lib/prisma'

// 获取计数值
export async function GET() {
  const counter = await prisma.counter.findFirst()
  return NextResponse.json({ value: counter?.value ?? 0 })
}

// 计数 +1
export async function POST() {
  const counter = await prisma.counter.upsert({
    where: { id: 1 },
    update: { value: { increment: 1 } },
    create: { id: 1, value: 1 },
  })
  return NextResponse.json({ value: counter.value })
}

前端页面

app/page.tsx 中编写计数器组件:

javascript 复制代码
"use client";

import { useState, useEffect, use } from "react";

export default function CounterPage() {
  const [count, setCount] = useState<number | null>(null);

  // 初始加载时获取计数值
  useEffect(() => {
    fetch("/api/counter")
      .then(res => res.json())
      .then(data => setCount(data.value))
  }, [])

  const handleIncrement = async () => {
    const res = await fetch("/api/counter", {
      method: "POST",
    });
    const data = await res.json();
    setCount(data.value);
  }

  return (
    <main className="flex flex-col items-center justify-center min-h-screen gap-4">
      <h1 className="text-2xl font-bold">全栈计数器</h1>
      <p className="text-4xl font-bold">当前计数:{count ?? "加载中.."}</p>
      <button onClick={handleIncrement}
        className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600"
      >点击加1</button>
    </main>
  )
}

运行效果

启动开发服务器:

arduino 复制代码
npm run dev

浏览器访问 http://localhost:3000,可以看到计数器初始值为 0

点击按钮,值会自增,并且数据会实时存储到数据库中。刷新页面时,数据依旧保持。


数据流转回顾

整个流程可以总结为:

  1. 前端页面 初始加载 → 调用 GET /api/counter → 获取数据库计数值
  2. 用户点击按钮 → 调用 POST /api/counter → Prisma 更新数据库 → 返回新值
  3. 前端收到返回值 → 更新页面显示

总结

到这里,我们完成了一个完整的 Next.js 全栈计数器应用

它包含了:

  • 数据库建模(Prisma)
  • 服务端接口(API Routes)
  • 前端交互(React Hooks + Fetch API)

这个例子虽然简单,却完整展示了 Next.js 的全栈能力,后续我将对 渲染模式(CSR / SSR / SSG) 进行深入探索以及搭建一个成熟的 博客系统

相关推荐
程序设计实验室1 天前
在Next.js中集成swagger文档
web前端·next.js
Mintopia2 天前
Next.js 新数据获取三剑客:fetch() + cache() + use —— 从引擎盖下聊到赛道上
前端·javascript·next.js
章丸丸2 天前
Tube - Studio Layout
react.js·next.js
小Lu的开源日常3 天前
Mathcheap v0.9.x 发布的第一个月,从想法到 MVP(最小可行性产品)
前端·图像识别·next.js
Mintopia4 天前
🌌 Next.js 服务端组件(Server Components)与客户端组件(`"use client"`)
前端·javascript·next.js
我想说一句5 天前
Next.js+Ollama本地聊天模型应用!
前端·next.js·ollama
Mintopia5 天前
App Router 与 `/app` 目录结构 & 布局系统的奇妙冒险 🏰
前端·javascript·next.js
FogLetter5 天前
Prisma + Next.js 全栈开发初体验:像操作对象一样玩转数据库
前端·后端·next.js
Mintopia6 天前
🛡️ Next.js 中间件权限验证与 API 保护的奇幻冒险
前端·javascript·next.js