Vercel 的部署体验以"简单流畅"著称,但生产环境中仍可能遇到各种各样的问题:从构建阶段 TypeScript 报错到 Function 运行时超时,从 Prisma 生成失败到自定义域名 404,从内存溢出到路由冲突。本文基于大量真实项目的排障经验,按构建阶段 → 运行阶段 → 网络层三层排查,给你一套系统性的诊断流程和修复方案。
一、构建阶段故障
1.1 构建失败的通用排查流程
1. 查看 Vercel Dashboard → Deployments → 点击失败的部署 → Build Logs
2. 定位第一个 ERROR/FAIL 行(通常后续错误是该错误的连锁反应)
3. 用 Ctrl+F 搜索 "error:" / "failed:" / "cannot find" 等关键词
4. 根据错误类型 → 对应下方章节排查
5. 本地复现:`npm run build`(不是 `npm run dev`,dev 和 build 行为不同)
1.2 TypeScript / ESLint 错误导致构建失败
错误示例:
Failed to compile.
./src/app/page.tsx:12:5
Type error: Type '{ blogs: any[]; }' is not assignable to type 'IntrinsicAttributes & Props'.
排查步骤:
# 1. 本地完整构建(development 会跳过类型检查)
npm run build
# 2. 单独检查类型
npx tsc --noEmit
# 3. 如果确认类型检查过于严格,临时放宽(不推荐长期使用)
// tsconfig.json
{
"compilerOptions": {
"strict": false, // 临时关闭严格模式
"noEmit": true
}
}
// next.config.js
module.exports = {
typescript: {
ignoreBuildErrors: true, // ⚠️ 仅临时用
},
eslint: {
ignoreDuringBuilds: true, // ⚠️ 仅临时用
},
};
注意:
ignoreBuildErrors只是跳过 TS 检查,问题代码仍然会让生产环境出错。建议先用它过构建,然后在本地用tsc --noEmit真修复。
1.3 依赖安装失败
错误示例:
npm ERR! code ERESOLVE
npm ERR! ERESOLVE could not resolve
修复:
# 1. 删除 lock 文件和 node_modules,重新安装
rm -rf node_modules package-lock.json
npm install
# 2. 如果使用 pnpm
rm -rf node_modules pnpm-lock.yaml
pnpm install
# 3. 检查 Node.js 版本(Vercel 默认使用 package.json engines 或项目设置)
# 在 Vercel Dashboard → Settings → General → Node.js Version 中设置
1.4 找不到模块(Module Not Found)
错误示例:
Error: Cannot find module '@/lib/prisma'
排查:
// tsconfig.json / jsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./*"] // 或 ["./src/*"],对应你的目录结构
}
}
}
// package.json — 确认没有漏装依赖
{
"dependencies": {
"@prisma/client": "^5.0.0"
}
}
1.5 Prisma 生成失败
错误示例:
Error: @prisma/client did not initialize yet.
原因:prisma generate 没有执行,导致 @prisma/client 不可用。
修复:
// package.json
{
"scripts": {
"build": "prisma generate && next build",
"postinstall": "prisma generate" // 确保 npm install 时自动执行
}
}
# 确认 prisma/schema.prisma 存在
ls prisma/schema.prisma
# 确认生成后文件存在
ls node_modules/.prisma/client/
1.6 环境变量缺失
错误示例:
Error: Missing environment variable DATABASE_URL
排查:
# 1. 本地检查 .env
env | grep DATABASE_URL
# 2. Vercel Dashboard → Settings → Environment Variables
# 确认 Production 和 Preview 环境都配置了
# 3. 如果本地 .env 有但生产没有,重新添加并 Redeploy
vercel env add DATABASE_URL
1.7 内存不足(OOM)
错误示例:
FATAL ERROR: Ineffective mark-compards near heap limit Allocation failed - JavaScript heap out of memory
修复:
# 增大 Node.js 堆内存
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build
// next.config.js
module.exports = {
// 减少并发,降低内存峰值
experimental: {
workerThreads: false,
cpus: 2,
},
// 或关闭静态优化
images: {
unoptimized: true, // 如果构建卡在图片优化
},
};
二、运行阶段故障
2.1 Serverless Functions 超时(504)
现象:页面/api 请求停顿后返回 504 GATEWAY_TIMEOUT
排查:
Vercel Dashboard → Logs → 选择 Function 执行记录
→ 查看 Duration
→ 如果超过限制(Hobby 10s / Pro 60s)→ 超时
修复策略:
// 1. 添加日志定位慢操作
export default async function handler(req: NextRequest) {
console.time('db-query');
const data = await db.query.largeTable();
console.timeEnd('db-query'); // 查看哪一步最慢
return Response.json(data);
}
// 2. 使用流式响应避免超时(AI 场景)
import { streamText } from 'ai';
export const runtime = 'edge'; // Edge 函数 30s/60s 限制比 Node.js 更灵活
const result = streamText({
model: openai('gpt-4'),
messages,
});
return result.toDataStreamResponse();
// 3. 分页/分批处理大数据
async function getLargeDataSet() {
const batchSize = 100;
let cursor = null;
const allData = [];
do {
const batch = await db.findMany({
take: batchSize,
skip: cursor ? 1 : 0,
cursor: cursor ? { id: cursor } : undefined,
});
allData.push(...batch);
cursor = batch[batch.length - 1]?.id;
} while (cursor);
return allData;
}
2.2 冷启动慢(首次访问延迟高)
现象:一段时间不访问后,首次请求耗时 1-5s
原因:Vercel Serverless Functions 在无请求时会冻结,下次请求时重新初始化(冷启动)。
缓解策略:
// 1. 用 Edge Functions(冷启动 < 5ms)替代 Node.js Functions
export const runtime = 'edge';
// 2. 在页面级别使用 ISR,让 CDN 服务缓存
export const revalidate = 3600;
// 3. 外部预热服务(如 Pingdom / UptimeRobot)每 5 分钟 ping 一次
2.3 404 路由错误
现象:
- 本地开发正常,部署到 Vercel 后某些页面 404
- App Router 和 Pages Router 同时存在时路由冲突
排查清单:
# 1. 确认文件位置正确(App Router)
ls src/app/blog/[slug]/page.tsx # ✅
ls src/app/blog/[slug].tsx # ❌ App Router 不是这样
# 2. 确认文件位置正确(Pages Router)
ls src/pages/blog/[slug].tsx # ✅
# 3. App Router + Pages Router 并存时,App Router 优先
# 如果有冲突,重命名 Pages Router 路由
// 4. 确认 generateStaticParams 返回了有效参数
export async function generateStaticParams() {
const posts = await fetchPosts();
return posts.map(p => ({ slug: p.slug }));
// 如果 posts 为空 → build 时不会生成页面
}
2.4 500 Internal Server Error
排查流程:
1. Vercel Dashboard → Logs → Functions → 筛选 500 错误
2. 查看堆栈追踪,定位出错函数和行号
3. 检查:
- 环境变量是否正确
- 数据库连接是否成功
- 外部 API 是否超时
- 是否有未捕获的 Promise 异常
// 全局错误处理
// app/error.tsx(App Router 全局错误边界)
'use client';
export default function ErrorBoundary({ error, reset }: { error: Error; reset: () => void }) {
return (
<div>
<h2>Something went wrong!</h2>
<p>{error.message}</p>
<button onClick={reset}>Try again</button>
</div>
);
}
// app/global-error.tsx(根级错误处理)
export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
return (
<html>
<body>
<h2>Global Error</h2>
<button onClick={reset}>Reload</button>
</body>
</html>
);
}
2.5 Prisma / 数据库连接问题
现象:API 返回 500,日志显示 Connection refused 或 query timed out
排查:
# 1. 测试数据库连通性(本地)
psql "$DATABASE_URL" -c "SELECT 1"
# 2. 确认 DATABASE_URL 在 Vercel 环境变量中配置正确
# 特别注意:部分云数据库的连接 URL 有 IP 白名单限制
# 3. Prisma 连接串格式检查
# 正确:postgresql://user:password@host:5432/db?schema=public
# 错误:postgresql://user:password@host/db(缺少端口)
// 4. Prisma Client 单例模式
// lib/prisma.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = global as unknown as { prisma: PrismaClient };
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
// 5. 如果连接频繁断开,添加连接池参数
// DATABASE_URL 中添加参数:
// postgresql://...?connection_limit=5&pool_timeout=10
三、网络与域名故障
3.1 自定义域名 404/不生效
排查清单:
# 1. DNS 是否解析到 Vercel
dig www.yourdomain.com +short
# 应该返回 cname.vercel-dns.com 或 Vercel 的 IP
# 2. SSL 证书状态
# Vercel Dashboard → Domains → 查看 SSL 状态
# 可能需要 24 小时自动签发
# 3. CNAME 是否正确
dig CNAME www.yourdomain.com +short
# 预期:cname.vercel-dns.com
3.2 SSL 证书问题
现象:浏览器提示 “不安全” / “NET::ERR_CERT_COMMON_NAME_INVALID”
修复:
- 确认域名已完全传播(DNS 传播可能需要 24-48 小时)
- Vercel Dashboard → Domains → 点击 “Refresh” 重新验证
- 如果之前用 Cloudflare → 确保 DNS 记录是 “DNS only”(灰色云朵),等 Vercel SSL 签发后再开启 Proxy
3.3 国内访问慢 / 不稳定
参照 Vercel 国内访问优化指南:
# 1. 检查默认域名是否被污染
nslookup your-project.vercel.app
# 如果返回异常 IP → 使用自定义域名
# 2. Ping 测试(从国内)
ping www.yourdomain.com
# 期望 < 100ms(如果 Cloudflare Proxy 已配置)
# 3. 检查 Cloudflare 配置
# 确保橙云代理已开启
# DNS 记录:CNAME www cname.vercel-dns.com Proxied
四、常见错误代码速查
| HTTP 状态 | 常见原因 | 修复方向 |
|---|---|---|
| 400 | 请求参数错误 | 检查 API 请求体格式 |
| 401 | 未授权 | 检查 Token/Session/Cookie |
| 403 | 禁止访问 | 检查 CORS/防火墙/IP 限制 |
| 404 | 路由不存在 | 检查文件路径、generateStaticParams |
| 405 | 方法不允许 | 检查 API Route 是否支持该 HTTP 方法 |
| 500 | 服务器内部错误 | 查看 Function Logs 堆栈 |
| 502 | 网关错误 | 上游服务(数据库/API)不可用 |
| 504 | 网关超时 | Functions 超时、数据库慢查询 |
五、调试技巧
5.1 本地复现生产问题
# 1. 使用 Vercel CLI 本地运行(最接近生产环境)
npm i -g vercel
vercel dev
# 2. 带环境变量运行
vercel --prod # 部署到 production(谨慎使用)
# 3. 查看远程日志
vercel logs --all
5.2 日志查询
# Vercel CLI 查日志
vercel logs your-project.vercel.app
# 筛选特定时间段
vercel logs --since "2025-11-20T10:00:00Z"
# 只看错误
vercel logs --all | grep ERROR
5.3 Preview 环境调试
# 每个 PR 自动生成 Preview URL
# 在 PR 的 Checks 中找到 "Visit Preview" 链接
# 用 Preview 环境测试不会污染 Production
# Preview 环境使用 Preview 环境变量
六、性能优化检查清单
6.1 Core Web Vitals 优化
| 指标 | 目标 | 优化方法 |
|---|---|---|
| LCP(最大内容绘制) | < 2.5s | 图片优化、CDN 缓存、字体优化 |
| FID(首次输入延迟) | < 100ms | 减少 JS 包大小、代码分割 |
| CLS(累积布局偏移) | < 0.1 | 图片尺寸声明、字体加载策略 |
| TTFB(第一字节时间) | < 600ms | ISR/SSG、Edge Functions |
6.2 Lighthouse 优化建议
# Chrome DevTools → Lighthouse → 分析
# 常见优化点:
# 1. Image format:使用 WebP/AVIF
# 2. Lazy loading:非首屏图片延迟加载
# 3. Preconnect:添加 DNS 预解析
# 4. Font display:使用 font-display: swap
七、安全排查
7.1 环境变量泄露检查
# 1. 确保 .env 在 .gitignore 中
grep env .gitignore
# 2. 检查提交历史是否泄露过密钥
git log --all --full-history -S "sk-" # 搜索 OpenAI API Key 模式
# 3. 如果泄露,立即轮换密钥
# 并在 Vercel Dashboard 更新环境变量
7.2 CORS 配置
// app/api/cors-example/route.ts
export async function GET(request: Request) {
return new Response(JSON.stringify({ message: 'OK' }), {
headers: {
'Access-Control-Allow-Origin': 'https://yourdomain.com',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
});
}
常见问题(FAQ)
怎么看 Vercel Function 的执行时间?
Vercel Dashboard → Logs → Functions → 每行日志右侧显示 Duration。或者用 console.time / console.timeEnd 手动标记。
Vercel 支持 SSH 到服务器调试吗?
不支持。Vercel 是纯 Serverless 平台,没有持久化的服务器实例。调试依赖日志和本地复现。
部署后直接 404 怎么办?
- 检查文件是否在正确的路由目录(App Router / Pages Router)
- 检查
next.config.js是否有output: 'export'(纯静态导出不能有 API routes) - 检查是否有
vercel.json覆盖路由规则 - 确认构建产物中包含目标路由:
ls .next/server/app/
本地正常但生产报错怎么办?
- 检查环境变量差异(生产 vs 开发)
- 检查 Node.js 版本差异
- 检查
NODE_ENV影响的行为 - 检查是否有只在生产启用的中间件/功能
如何回滚到上个版本?
Vercel Dashboard → Deployments → 找到上次成功的部署 → 点击三个点 → “Promote to Production”。整个过程 1-2 秒完成。
相关阅读
- Vercel 详解:前端与 AI 应用的一站式云平台
- Vercel 国内访问优化指南
- Vercel 定价与成本详解
- Vercel Edge Functions 深度指南
- Vercel Middleware 实战指南
- Vercel ISR 完整指南
- Vercel 部署 Nuxt.js (Vue) 实战
- Vercel 专题导航
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。