You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Prisma:如何在开发环境中检测待处理数据库迁移?

解决T3 Stack开发环境中Prisma迁移未执行的问题

背景

基于T3 Stack(Next.js + Prisma ORM + TypeScript)开发应用时,拉取同事代码经常会遇到新的数据库迁移文件,但开发环境数据库没同步执行这些迁移,导致应用出现各种莫名异常,要花大量时间排查才发现根源是迁移没跑。

期望实现

  • 开发环境启动时,若存在待处理迁移,直接让应用崩溃并给出明确提示(类似Ruby on Rails的默认行为)
  • 开发服务器运行时(依赖热重载,开发者常不重启),若有未处理迁移,让所有HTTP请求失败并显示友好提示

疑问解答与实现方案

1. 如何在代码中获取Prisma迁移状态

Prisma Client确实没有直接提供迁移状态的API,但可以通过Node.js的child_process调用Prisma CLI的migrate status命令,解析输出结果来判断是否有待执行迁移。

示例代码:

import { execSync } from 'child_process';

export async function hasPendingMigrations(): Promise<boolean> {
  try {
    // 执行prisma migrate status并获取JSON格式输出
    const output = execSync('npx prisma migrate status --json', { encoding: 'utf-8' });
    const status = JSON.parse(output);
    
    // 判断是否存在待执行迁移
    return status.pendingMigrations.length > 0;
  } catch (error) {
    // 命令执行失败(比如无迁移目录),默认视为无待处理迁移
    return false;
  }
}

⚠️ 注意:这个逻辑只在开发环境使用,生产环境不要调用CLI命令,避免性能和安全问题。

2. 在每个HTTP请求中间件中添加检查的影响

  • 性能损耗:每次请求都执行migrate status会增加请求延迟,开发环境虽对性能要求不高,但频繁调用仍有感知。可以优化为缓存检查结果,比如每隔30秒重新检查一次,而非每次请求都触发。
  • 热重载兼容性:Next.js热重载会重新执行代码,缓存逻辑要注意避免内存泄漏,也可以监听迁移目录的文件变化,触发重新检查。
  • 开发体验:能及时拦截请求并提示迁移,避免无意义的调试,但如果检查逻辑误判,会导致所有请求失败,反而影响开发效率。

3. 其他可选解决方案

  • 启动脚本强制检查:在package.json的dev脚本中前置迁移检查,比如:
    "scripts": {
      "dev": "node scripts/check-migrations.js && next dev"
    }
    
    在check-migrations.js中调用上述hasPendingMigrations方法,若返回true则抛出错误终止进程。
  • Git钩子:配置post-checkout或post-pull钩子,拉取代码后自动检查迁移,提示开发者执行prisma migrate dev。
  • 开发环境自动执行迁移:启动时自动执行prisma migrate dev,但要注意这会直接修改数据库,适合团队共用开发数据库的场景,或配合种子脚本恢复测试数据。
  • 自定义Next.js服务器:用自定义服务器替代默认dev服务器,在启动时执行迁移检查,同时定期在运行中重新校验。

具体实现示例

启动时检查(Next.js 13+ App Router)

在app/globals.ts中添加启动校验:

import { hasPendingMigrations } from '@/utils/migrate-check';

if (process.env.NODE_ENV === 'development') {
  (async () => {
    const pending = await hasPendingMigrations();
    if (pending) {
      console.error('❌ 存在待执行的数据库迁移,请先运行:npx prisma migrate dev');
      process.exit(1); // 终止应用启动
    }
  })();
}

请求中间件检查(Next.js Middleware)

在middleware.ts中添加全局请求拦截:

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { hasPendingMigrations } from '@/utils/migrate-check';

// 缓存检查结果,减少重复执行
let lastCheckedTimestamp = 0;
let hasPending = false;

export async function middleware(request: NextRequest) {
  if (process.env.NODE_ENV !== 'development') {
    return NextResponse.next();
  }

  // 每隔30秒重新检查一次
  const now = Date.now();
  if (now - lastCheckedTimestamp > 30000) {
    hasPending = await hasPendingMigrations();
    lastCheckedTimestamp = now;
  }

  if (hasPending) {
    return new NextResponse(
      '⚠️ 请先执行数据库迁移:npx prisma migrate dev',
      { status: 503, headers: { 'Content-Type': 'text/plain' } }
    );
  }

  return NextResponse.next();
}

// 配置中间件生效范围(排除静态资源)
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

内容的提问来源于stack exchange,提问作者Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:27:44