☰
从零到上线:Next.js 接入 PlanetScale MySQL 的完整实战指南
2026/10/5 13:08:35 网站建设 项目流程

从零到上线:Next.js 接入 PlanetScale MySQL 的完整实战指南

【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js

Next.js 官方仓库的with-mysql示例,把 App Router、Prisma ORM 与托管数据库 PlanetScale MySQL 装进一个可运行的电商商品列表里。跟着走一遍,你能拿到一套"云端建库 → 本地跑通 → 部署上线"的完整 MySQL 接入流程,而且每个环节都知道它为什么这么设计。

先看地图:谁负责什么

这套示例的分工非常克制,每个文件只干一件事:

路径职责
prisma/schema.prisma定义 Product / Category 模型与客户端生成器
prisma/data.ts3 个分类、4 件商品的种子数据
prisma/seed.ts清空旧数据并批量灌入种子
prisma.config.ts为 Prisma CLI 提供 schema 路径与连接串来源
lib/prisma.ts运行时数据库客户端(全局单例封装)
app/page.tsx服务端组件,直接查库渲染商品网格
components/Product.tsx单张商品卡片
.env.exampleDATABASE_URL连接串模板

技术组合是 Next.js(App Router)+ Prisma(新版 TypeScript 客户端)+@prisma/adapter-planetscale驱动适配器 + Tailwind CSS v4。适配器把 SQL 通过 HTTPS 发往 PlanetScale 网关,所以运行时依赖里才有undici——它给适配器提供 fetch 实现,客户端本身不走 MySQL 协议。

认证 CLI 并建库:把引擎类型和默认分支定下来

🔑 动手前先装好 PlanetScale CLI,用pscale auth login完成浏览器授权,之后所有命令都靠这份本地凭据。

建库命令很短:

pscale database create <DATABASE_NAME> --engine mysql

输出里会告诉你数据库创建成功。值得注意的隐藏事实是:建库同时自动生成了一个名为main的分支,PlanetScale 的 schema 变更都发生在分支上,main就是后续所有操作的起点。引擎类型必须在建库时用--engine mysql钉死,Postgres 是另一套模板,两者的适配器和连接串格式完全不通用,事后换不掉。

拉下模板工程:一条命令装齐全部依赖

凭据有了,接下来把代码拉下来:

npx create-next-app --example with-mysql nextjs-mysql

yarn / pnpm / bun 也有对应写法。执行完会在nextjs-mysql目录里装好 package.json 声明的全部依赖:运行时是next、react、@prisma/client、@prisma/adapter-planetscale、undici;开发侧是prismaCLI、tsx(跑种子脚本)、dotenv(加载.env)和 Tailwind v4。依赖看着不多,但每个都有明确职责,这也是后面排查问题时的排查清单。

生成凭据拼连接串:明文密码只展示一次

先复制模板文件:

mv .env.example .env

然后给main分支创建一组凭据:

pscale password create <DATABASE_NAME> main <PASSWORD_NAME>

输出会长这样——明文密码只展示这一次,务必当场保存:

NAME USERNAME ACCESS HOST URL ROLE PLAIN TEXT <PASSWORD_NAME> xxxxxxxxxxxxx xxxxxx.us-east-2.psdb.cloud Can Read & Write pscale_pw_xxxxxxx

把四个字段拼进.env的DATABASE_URL:

参数来源说明
<USERNAME>输出的USERNAME数据库用户名
<PLAIN_TEXT_PASSWORD>输出的PLAIN TEXT只出现一次的明文密码
<ACCESS_HOST_URL>输出的ACCESS HOST URL访问域名,末尾别加斜杠
<DATABASE_NAME>建库时的名称目标库名
?sslaccept=strict固定追加强制 TLS

同一分支允许多组凭据,PASSWORD_NAME就是给这组凭据贴的用途标签——开发一组、生产一组,轮换时互不影响。这条连接串会被两边消费:Prisma CLI 从 prisma.config.ts 的env("DATABASE_URL")读,应用运行时从process.env.DATABASE_URL读,所以格式拼错一次,两边同时报错。

看懂数据模型:连接串为什么不写进 schema

打开 prisma/schema.prisma 会看到两个模型和一处刻意的留白:

generator client { provider = "prisma-client" output = "../lib/generated/prisma" }
  • 客户端输出到lib/generated/prisma而不是传统的node_modules/.prisma,因此应用和种子脚本都从@/lib/generated/prisma/client导入类型,生成产物跟着代码库走;
  • datasource块里没有url,连接串统一由 prisma.config.ts 提供。这是新版 Prisma 的推荐做法:schema 只描述"结构",环境相关的信息集中到一处,改库名不用动 schema;
  • relationMode = "prisma"表示外键完整性由应用层维护,适配 PlanetScale 不允许传统外键约束的默认场景;
  • price用Decimal而不是浮点数,种子数据里配合new Prisma.Decimal(19.95)构造,避免货币精度丢失。

模型本身是一对多:Product通过categoryId引用Category并加了@@index([categoryId]),按分类筛选商品时走索引。

推模型灌种子:三条命令把空库变成商品库

凭据配好后按顺序执行:

npx prisma generate # 按 schema 生成类型安全的客户端 npx prisma db push # 把模型直接同步成数据库表结构 npx prisma db seed # 写入演示数据

db push不生成迁移文件,适合原型阶段;想留迁移历史就换成migrate系列命令。db seed实际执行的是 package.json 里prisma.seed声明的tsx prisma/seed.ts。

种子脚本的策略是幂等重建:先deleteMany()清空两张表,再用$executeRaw把AUTO_INCREMENT重置为 1,然后createMany批量写入 data.ts 里的 3 个分类和 4 件商品。重置自增是必要的——商品通过categoryId: 1/2/3硬关联分类主键,不重置的话第二次灌数据时外键就会指向不存在的 id。脚本重复执行永远安全,这对你调试期间反复灌库非常友好。

跑通本地页面:单例防止连接爆炸

npm run dev

访问http://localhost:3000,能看到渲染出来的商品网格:

数据流向是 app/page.tsx 这个 async 服务端组件直接执行prisma.product.findMany({ include: { category: true } }),一次联表取出商品和所属分类,再逐项传给Product卡片组件。没有中间的 API 层,客户端只收到 HTML——这是 App Router 推荐的取数姿势。

真正值得逐行看的是 lib/prisma.ts:

const prisma = globalForPrisma.prisma ?? createPrismaClient(); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

为什么非要挂在globalThis上?因为 Next.js 开发模式下,每次文件变更都会重新执行模块代码,如果每轮都new PrismaClient(),相当于每次保存都新开一条数据库连接,连接数很快顶到上限。把实例挂到全局后,热更新只创建一次,后续全部复用;生产环境模块只加载一次,所以只在非生产环境才写全局。

部署前提升分支:生产流量只走被提升的 main

🚀 本地跑通后,上线前还差一个数据库动作:

pscale branch promote <DATABASE_NAME> main

在 PlanetScale 里,main分支默认是开发角色,只有被提升为生产分支后,生产流量才有资格访问它。不提升就直接部署,线上请求会因为没有可用的生产凭据路径而失败。提升后,你可以复用之前那组密码,也可以新跑一次pscale password create给生产单独配一组——推荐后者,开发和生产凭据隔离,出问题时能立刻轮换生产而不动本地。

最后是部署平台侧:把项目导入部署平台,在环境变量里填上生产DATABASE_URL即可。由于页面全是服务端渲染,构建期不需要连库,每次请求时实时查 PlanetScale。

排错清单:现象、原因与处置

🧯 按出现频率排序:

现象原因处置
PrismaClientInitializationError/ 连接失败连接串四个字段没替换全,或域名末尾多了路径对照 CLI 输出逐字段核对,保留?sslaccept=strict
页面是空的,没有商品只跑了generate,没跑db push和db seed补跑后两条命令,种子可重复执行
种子脚本报找不到DATABASE_URLdotenv/config依赖当前目录是项目根在nextjs-mysql根目录执行命令
开发期连接数超限绕过单例直接new PrismaClient()统一从 lib/prisma.ts 导入
线上 401 或连不上库分支没提升,或用了开发凭据访问生产pscale branch promote并换生产连接串

提示:连接串的四个字段都来自pscale password create的同一次输出,缺一个都连不上;保存密码的那步输出是唯一窗口,丢了只能重新password create一组新凭据。

如何迁移到自己的项目

这套骨架可以直接当模板用,替换点集中在三处:

  1. 模型:改 prisma/schema.prisma 为你的业务表,保留prisma-client生成器与prisma.config.ts的连接串外置写法,重新prisma generate+db push;
  2. 种子数据:把你的初始数据放进prisma/data.ts,照抄 seed.ts 的"清空 → 重置自增 → 批量写入"流程,保证可重复执行;
  3. 取数与渲染:在服务端组件里 import lib/prisma.ts 导出的单例实例做查询,不要自己new客户端。

环境差异只在凭据:本地一组、生产一组,连接串格式不变。把这三层解耦记牢,之后换数据库供应商时你只需要换适配器和连接串,业务代码一行不动。

【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询