Vercel 部署故障排查指南:构建失败、函数超时、路由错误与性能优化

系统性覆盖 Vercel 部署最常见问题的诊断与修复:构建失败排查流程、Serverless Functions 超时与冷启动、Prisma/数据库连接、路由 404/403、域名 SSL、环境变量、内存溢出、Edge Function 故障、第三方集成断开、平台限制速查、自动化监控告警等 20+ 个高频故障场景,含排查清单与修复命令。

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, // 如果构建卡在图片优化
  },
};

1.8 构建时间过长的优化

现象:大型 Monorepo 或依赖复杂的项目构建时间超过 Vercel 限制(Hobby 45 分钟 / Pro 60 分钟),导致部署失败或排队。

原因与修复

1. Monorepo 构建超时

# 使用 Turborepo 远程缓存,避免每次全量构建
# vercel.json
{
  "buildCommand": "turbo run build --remote-cache"
}
# 在 Vercel Dashboard → Settings → Environment Variables 添加
TURBO_TOKEN=your_token
TURBO_TEAM=your_team_slug
TURBO_REMOTE_CACHE_SIGNATURE_KEY=your_signature_key

2. 依赖安装优化

# 强制使用 lock 文件,避免解析耗时
# package.json 中添加 engines
{
  "packageManager": "pnpm@9.0.0",
  "engines": {
    "node": "20.x"
  }
}
# Vercel 构建时自动使用 pnpm 的 frozen-lockfile,显著减少安装时间
# 无需额外配置,只要存在 pnpm-lock.yaml 即可

3. 增量构建策略

// next.config.js
module.exports = {
  // 启用实验性增量编译(Next.js 14+)
  experimental: {
    incrementalCacheHandlerPath: require.resolve('./cache-handler'),
  },
  // 只对变更页面重新静态生成
  staticPageGenerationTimeout: 120,
};

4. 构建产物过大导致上传超时

# 检查 .next 目录体积
du -sh .next/

# 如果超过 250MB(Hobby 限制),优化方向:
# 1. 将图片迁移至外部 CDN(Cloudflare R2 / AWS S3)
# 2. 禁用不必要的 Source Map
echo "NEXT_TELEMETRY_DISABLED=1" >> .env
// next.config.js
module.exports = {
  productionBrowserSourceMaps: false,
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.yourdomain.com' },
    ],
  },
};

二、运行阶段故障

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 refusedquery 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

2.6 Edge Function 故障排查

现象:Edge Function 返回 500 或编译失败,日志提示模块缺失或体积超限。

1. Edge Runtime 与 Node.js 的兼容性问题

Edge Runtime 基于 V8 隔离环境,不支持 Node.js 原生模块:

// ❌ 以下模块在 Edge Runtime 中不可用
import fs from 'fs';
import { createServer } from 'net';
import crypto from 'crypto'; // 部分 API 缺失
// ✅ 使用 Web 标准 API 替代
// fs → 使用 fetch 从外部存储读取
// crypto → 使用 Web Crypto API
const encoder = new TextEncoder();
const data = encoder.encode('hello');
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
// ✅ 条件性导入(同一文件兼容两种 Runtime)
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export async function GET(req: NextRequest) {
  // 只在 Edge Runtime 中运行
  const { searchParams } = new URL(req.url);
  return Response.json({ ok: true });
}

2. Edge Function 代码体积超限(1MB 限制)

# 检查打包后体积
ls -la .vercel/output/functions/_func.func/index.js
# 如果 > 1MB → 需要瘦身
// next.config.js
module.exports = {
  // 将重型依赖拆分为 Node.js Function
  // 在路由级别指定 runtime
};
// app/api/heavy-task/route.ts
export const runtime = 'nodejs'; // 需要重型库时用 Node.js Runtime

3. Edge Function 运行时异常排查

# Edge Function 日志与 Node.js Function 日志查看方式相同
vercel logs --all | grep "edge"

# 常见异常:
# - Error: Dynamic code evaluation is not allowed → 避免 eval/new Function
# - Error: Module not found → 检查依赖是否兼容 Edge

4. Edge vs Node.js Function 的选择错误

场景推荐 Runtime原因
简单 API / 中间件 / 鉴权Edge冷启动快,全球就近执行
文件系统操作 / 原生模块Node.js需要 fs/net/child_process
数据库 ORM(Prisma)Node.jsPrisma Client 需 Node.js 绑定
AI 流式响应Edge支持 Streaming,延迟低
图像处理(Sharp)Node.jsSharp 依赖原生 libv8

判断方法:如果 npm ls <package> 显示该包依赖 nan / node-gyp / bindings,则只能在 Node.js Runtime 中使用。


三、网络与域名故障

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”

修复

  1. 确认域名已完全传播(DNS 传播可能需要 24-48 小时)
  2. Vercel Dashboard → Domains → 点击 “Refresh” 重新验证
  3. 如果之前用 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

四、第三方集成故障

4.1 GitHub 集成断开(Webhook 失效)

现象:Push 代码后 Vercel 没有自动部署,或 PR 没有生成 Preview。

排查

1. Vercel Dashboard → Project Settings → Git → 查看连接状态
2. GitHub → Repository → Settings → Webhooks → 查看 vercel.app webhook
   → 如果显示红色 ❌ → 点击 "Redeliver" 测试
3. 检查 GitHub App 权限:
   GitHub → Settings → Applications → Vercel → Repository access

修复

Vercel Dashboard → Project Settings → Git → Disconnect → 重新连接 GitHub Repository
# 如果 Webhook 频繁失效,检查是否因为仓库转移或改名
git remote -v
# 确认 remote URL 与 Vercel 中配置的仓库一致

4.2 OAuth 认证过期重新连接

现象:团队成员无法部署,提示权限不足;或个人账号授权过期。

修复

1. Vercel Dashboard → Settings → Git Provider → GitHub
2. 点击 "Disconnect" → 清除浏览器缓存
3. 重新点击 "Connect" 并授权
4. 如果是 Organization 仓库 → 需要组织管理员在 GitHub 侧授权 Vercel App

4.3 Vercel Bot 评论配置

现象:GitHub PR 中没有看到 Vercel Bot 的 Preview 链接评论。

配置

Vercel Dashboard → Project Settings → Git → Pull Request Comments
→ 勾选 "Preview URL" 和 "Build Status"
→ 如果是 Organization 项目,需要管理员权限才能修改

4.4 Teams/Organizations 权限问题

现象:团队成员看不到项目、无法部署或无法查看日志。

排查

1. Vercel Dashboard → Settings → Members → 确认成员角色
   - Owner:全部权限
   - Member:可以部署和查看日志
   - Viewer:只读
2. GitHub Organization → Settings → Third-party Access → Vercel
   → 确认组织已授权 Vercel
3. 如果成员通过 SSO 登录 → 检查 SAML/SCIM 配置

4.5 部署队列拥塞的处理

现象:多个 PR 同时推送时,部署排队等待时间过长,影响开发效率。

排查与优化

# 查看当前部署队列
vercel ls

# 取消不必要的部署(如已废弃的 PR 预览)
vercel remove <deployment-url> --yes
优化策略:
1. 在 Vercel Dashboard → Settings → Git → Ignored Build Step
   添加脚本跳过不影响构建的文件变更:
   git diff --name-only HEAD^ HEAD | grep -v '\.md$' | grep -v '\.txt$'

2. 限制并发 Preview 部署数量:
   Project Settings → Git → Pull Request → "Only build when pull requests are ready for review"

3. 使用 Pro/Enterprise 计划获取更高的并发构建配额

五、常见错误代码速查

HTTP 状态常见原因修复方向
400请求参数错误检查 API 请求体格式
401未授权检查 Token/Session/Cookie
403禁止访问检查 CORS/防火墙/IP 限制
404路由不存在检查文件路径、generateStaticParams
405方法不允许检查 API Route 是否支持该 HTTP 方法
500服务器内部错误查看 Function Logs 堆栈
502网关错误上游服务(数据库/API)不可用
504网关超时Functions 超时、数据库慢查询

六、Vercel 平台限制速查表

6.1 函数执行时间限制

计划Node.js FunctionEdge Function
Hobby10 秒30 秒
Pro60 秒30 秒
Enterprise900 秒(15 分钟)30 秒

注意:Edge Function 无论计划均为 30 秒,但冷启动 < 5ms,更适合短响应场景。

6.2 请求与响应限制

限制项HobbyProEnterprise
请求体大小4.5 MB4.5 MB4.5 MB
响应体大小无限制(流式)无限制(流式)无限制(流式)
并发请求1000 / 区域3000 / 区域自定义

6.3 环境变量与构建限制

限制项HobbyProEnterprise
环境变量数量100 个100 个1000 个
单个环境变量大小4 KB4 KB64 KB
构建时间45 分钟60 分钟自定义
部署频率100 / 天无限制无限制
构建产物大小250 MB250 MB500 MB

6.4 自定义数量限制

限制项HobbyProEnterprise
团队成员无限制无限制无限制
项目数量无限制无限制无限制
自定义域名无限子域名无限子域名无限子域名
Serverless Function 数量12 / 部署24 / 部署自定义

超出限制时的表现

  • 构建超时 → 部署状态显示 BUILD_ERROR
  • 函数超时 → 浏览器返回 504 GATEWAY_TIMEOUT
  • 并发超限 → 新请求进入队列或返回 429 TOO_MANY_REQUESTS
  • 环境变量超限 → 部署时提示 ENV_VARIABLE_LIMIT_EXCEEDED

七、调试技巧

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(第一字节时间)< 600msISR/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',
    },
  });
}

十、自动化监控与告警

9.1 使用 Vercel Webhooks 集成 Slack/PagerDuty

Vercel 提供部署事件 Webhook,可集成到团队通知系统:

# 1. 在 Vercel Dashboard → Project Settings → Webhooks 添加 Endpoint
# URL: https://hooks.slack.com/services/your/webhook/url

# 2. 选择事件类型:
# - deployment.succeeded
# - deployment.failed
# - deployment.canceled
// 3. 自建 Webhook 接收端(如 Next.js API Route)
// app/api/webhooks/vercel/route.ts
import { NextRequest } from 'next/server';

export async function POST(req: NextRequest) {
  const payload = await req.json();

  if (payload.type === 'deployment.failed') {
    // 发送到 Slack / PagerDuty / 飞书
    await fetch('https://hooks.slack.com/services/...', {
      method: 'POST',
      body: JSON.stringify({
        text: `❌ 部署失败: ${payload.payload.url}\n项目: ${payload.payload.name}\n错误: ${payload.payload.error}`,
      }),
    });
  }

  return Response.json({ ok: true });
}

9.2 自定义 Uptime 监控

# 使用 Vercel Deploy Status API 检查部署状态
# 获取 Deployment ID
vercel ls --meta gitCommitRef=main

# 检查特定部署状态
curl -s "https://api.vercel.com/v13/deployments/<deployment-id>?teamId=<team>" \
  -H "Authorization: Bearer $VERCEL_TOKEN" | jq '.readyState'

# 预期返回: READY / ERROR / CANCELED / BUILDING
# 结合 Cron 定期检查(可用 GitHub Actions / Vercel Cron)
# vercel.json
{
  "crons": [
    {
      "path": "/api/health-check",
      "schedule": "*/5 * * * *"
    }
  ]
}

9.3 使用 Vercel CLI 自动化部署状态检查

#!/bin/bash
# deploy-check.sh - 在 CI/CD 中集成

DEPLOY_URL=$(vercel deploy --yes --no-wait)
echo "Deployment URL: $DEPLOY_URL"

# 等待部署完成
while true; do
  STATUS=$(vercel inspect $DEPLOY_URL --timeout=1 2>/dev/null | grep "Ready" || echo "pending")
  if echo "$STATUS" | grep -q "Ready"; then
    echo "✅ 部署成功"
    exit 0
  fi
  echo "⏳ 等待中..."
  sleep 5
done

9.4 GitHub Actions 中集成 Vercel 部署检查

# .github/workflows/deploy-check.yml
name: Check Vercel Deployment

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: vercel/action-deploy@v1
        id: vercel_deploy
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}

      - name: Wait for Deployment
        run: |
          DEPLOY_URL="${{ steps.vercel_deploy.outputs.deployment-url }}"
          for i in {1..30}; do
            STATUS=$(curl -s "$DEPLOY_URL/api/health" -o /dev/null -w "%{http_code}")
            if [ "$STATUS" = "200" ]; then
              echo "✅ 部署正常"
              exit 0
            fi
            sleep 10
          done
          echo "❌ 部署检查超时"
          exit 1

十一、常见问题(FAQ)

怎么看 Vercel Function 的执行时间?

Vercel Dashboard → Logs → Functions → 每行日志右侧显示 Duration。或者用 console.time / console.timeEnd 手动标记。

Vercel 支持 SSH 到服务器调试吗?

不支持。Vercel 是纯 Serverless 平台,没有持久化的服务器实例。调试依赖日志和本地复现。

部署后直接 404 怎么办?

  1. 检查文件是否在正确的路由目录(App Router / Pages Router)
  2. 检查 next.config.js 是否有 output: 'export'(纯静态导出不能有 API routes)
  3. 检查是否有 vercel.json 覆盖路由规则
  4. 确认构建产物中包含目标路由:ls .next/server/app/

本地正常但生产报错怎么办?

  1. 检查环境变量差异(生产 vs 开发)
  2. 检查 Node.js 版本差异
  3. 检查 NODE_ENV 影响的行为
  4. 检查是否有只在生产启用的中间件/功能

如何回滚到上个版本?

Vercel Dashboard → Deployments → 找到上次成功的部署 → 点击三个点 → “Promote to Production”。整个过程 1-2 秒完成。

部署卡在 Building 状态怎么处理?

现象:Dashboard 中部署状态长时间停留在 Building,超过正常构建时间。

排查

# 1. 查看实时构建日志(可能卡在某个步骤)
vercel logs <deployment-url> --all

# 2. 常见原因:
# - 大型依赖安装(如 Sharp、Puppeteer)
# - 静态生成页数过多(上千页)
# - 外部 API 在构建时调用超时
# - 内存不足导致 Node.js GC 频繁

修复

// 如果卡在图片优化 → 关闭静态图片优化
// next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
};
# 如果是 Puppeteer/PhantomJS 依赖导致安装慢 → 改用外部截图服务
# 如果是静态生成页数过多 → 改用 ISR,延迟生成

Preview 环境正常但生产环境失败怎么办?

排查

1. 确认环境变量差异:
   Vercel Dashboard → Settings → Environment Variables
   → 检查 Production 和 Preview 分别配置的变量是否一致

2. 检查数据库连接:
   Preview 可能连接开发数据库,Production 连接生产数据库
   → 生产数据库可能有 IP 白名单限制

3. 检查 NODE_ENV 差异:
   某些库在 production 模式下行为不同(如 Prisma 的加速模式)

账单/成本突然增加怎么排查?

排查路径

1. Vercel Dashboard → Billing → Usage
   → 查看 Function Invocations / Bandwidth / Build Minutes 哪项突增

2. 常见原因:
   - 被爬虫/攻击大量请求 API → 加 Rate Limiting
   - 图片未优化导致带宽暴增 → 启用 Next.js Image Optimization
   - 构建频率过高(每次 commit 都触发)→ 配置 Ignored Build Step
// 添加简单的 Rate Limiting
import {NextRequest} from 'next/server';

export async function middleware(req: NextRequest) {
  const ip = req.ip ?? '127.0.0.1';
  const key = `rate-limit:${ip}`;

  // 使用 Redis / Upstash Redis 计数
  // 超过 100 次/分钟 → 返回 429
}

大文件上传失败怎么处理?

现象:API Route 接收文件上传时返回 413 Payload Too Large

原因:Vercel Serverless Functions 请求体限制为 4.5MB(含 HTTP 头)。

解决方案

// 1. 如果文件 < 4.5MB → 确保 Body Parser 配置正确
// app/api/upload/route.ts
export const config = {
  api: {
    bodyParser: {
      sizeLimit: '4.5mb',
    },
  },
};
// 2. 如果文件 > 4.5MB → 使用预签名 URL 直传
// 客户端:请求后端生成 S3/R2 预签名 PUT URL
// 客户端:直接用 fetch PUT 上传到对象存储
// 客户端:上传完成后返回 URL 给后端保存

团队协作时部署冲突怎么处理?

现象:多个成员同时推送,后推送的覆盖了先推送的,导致功能丢失。

最佳实践

# 1. 每个人都通过 PR 部署,禁止直接 push 到 main
git branch feature/my-feature
git push origin feature/my-feature
# 在 GitHub 发起 PR,通过 Preview 验证后再合并
2. 合并策略:
   GitHub → Settings → Branches → main → Branch protection rules
   → Require pull request reviews before merging
   → Require status checks to pass(Vercel Build + 你的测试)

3. 如果冲突已发生:
   Vercel Dashboard → Deployments → 找到正确版本的部署 → Promote to Production

十二、故障排查工具箱

10.1 浏览器 Network 面板的高级用法

1. 查看请求是否命中 Vercel Edge Network:
   Network → 点击请求 → Response Headers → x-vercel-cache
   值:HIT(CDN 缓存)/ MISS(回源)/ STALE(缓存过期)/ BYPASS(跳过缓存)

2. 查看 Function 执行信息:
   x-vercel-id: sfo1::iad1-1234567890abcdef
           ↑
       请求处理区域(如 sfo1 = San Francisco)

3. 检查缓存策略:
   Cache-Control: s-maxage=3600, stale-while-revalidate=86400
   → ISR 的缓存头,3600 秒后重新生成

10.2 curl 命令测试 Vercel 部署

# 基础请求测试
curl -I https://your-project.vercel.app/

# 测试缓存行为
curl -I -H "Cache-Control: no-cache" https://your-project.vercel.app/

# 测试不同区域(通过 VPN 或 Cloudflare Worker)
# 检查 x-vercel-id 中的区域代码

# 测试 API 超时阈值
curl -w "@curl-format.txt" -o /dev/null -s https://your-project.vercel.app/api/slow-endpoint

# curl-format.txt 内容:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_total: %{time_total}\n

10.3 Vercel CLI 命令详解

# 查看实时日志(按项目)
vercel logs <project-url> --all --follow

# 查看特定函数的日志
vercel logs <project-url> --all | grep "/api/users"

# 查看部署详情(包含构建时间、环境变量等)
vercel inspect <deployment-url>

# 列出环境变量
vercel env ls

# 添加环境变量(交互式)
vercel env add DATABASE_URL

# 导出环境变量到本地
echo $(vercel env ls | grep DATABASE_URL | awk '{print $2}')

# 查看部署历史
vercel ls --meta gitCommitRef=feature/my-branch

# 回滚到某个部署
vercel --version <deployment-url>

10.4 第三方工具推荐组合

工具用途与 Vercel 的集成方式
Sentry错误追踪与性能监控@sentry/nextjs 自动捕获 500 错误和慢查询
Logflare结构化日志存储与分析Vercel Integration → Logflare,转发所有 Function Logs
UptimeRobot外部可用性监控设置每 5 分钟 ping 关键页面,Vercel 冷启动自动预热
Inngest后台任务队列(替代长时 Function)通过 Webhook 触发,Vercel Function 只做入队
Upstash Redis状态共享与限流Edge-compatible,支持 Rate Limiting 和 Session 存储

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「saas」更多文章

  1. 短链接对 SEO 的影响与优化最佳实践
  2. UTM 参数 + 短链接:追踪每一条营销链路
  3. 私域流量运营中的短链接策略:从引流到转化