vercel-deploy-nestjs
NestJS 部署到 Vercel 完整指南
从反复踩坑到成功部署,记录 NestJS 11 + Vercel 部署的所有坑和经验。
目录
最终方案(TL;DR)
NestJS 在 Vercel 上是零配置部署。 你不需要 vercel.json、api/index.ts、serverless-http 或任何特殊适配器。
只需确保:
src/main.ts使用标准的NestFactory.create()+app.listen()- Vercel 项目框架预设被正确识别为 NestJS(不是 Other)最好手动打开网站查看项目是否被标识为nestjs项目
- CORS 配置包含
OPTIONS方法和必要的头信息
项目背景
- 框架:NestJS 11
- 数据库:MongoDB(通过 TypeORM)
- 缓存:Redis(通过 ioredis)
- 认证:JWT + Passport
- 其他:阿里云人机验证、Resend 邮件服务、设备指纹加密
踩坑历程
坑一:用错了部署方式
最开始在网上找到的很多教程都用 @vercel/node + builds 的方式:
// ❌ 不需要这样
{
"builds": [
{ "src": "src/main.ts", "use": "@vercel/node" }
],
"routes": [
{ "src": "/(.*)", "dest": "src/main.ts" }
]
}
还有教程推荐用 ExpressAdapter + serverless-http 创建专门的 Serverless 入口文件 api/index.ts:
// ❌ 不需要这样
import { ExpressAdapter } from '@nestjs/platform-express';
import serverless from 'serverless-http';
这些方式在你搜到的旧文章里有效,但 Vercel 现在已经原生支持 NestJS 了。 加了这些反而干扰自动检测,导致构建失败或 404。
坑二:Vercel 项目预设错误
这是最隐蔽的坑。
现象:构建日志显示 npm run build 执行成功,但随即报错:
Error: No Output Directory named "public" found after the Build completed.
原因:Vercel 项目创建时框架预设被设成了 Other(或其他前端框架),导致 Vercel 在构建后去找 public/ 目录(这是静态网站的默认输出目录),而不是 NestJS 的 dist/ 目录。
解决:在 Vercel 控制台删除项目,重新从 GitHub 导入。Vercel 会全新检测依赖包中的 @nestjs/core,自动将框架预设设为 NestJS。
仅修改控制台的 Framework Preset 可能不生效(有缓存),重建项目最可靠。
验证方法:构建日志应该显示 Vercel 识别到了 NestJS:
Detected framework: NestJS
Build Command: npm run build
Output Directory: dist
坑三:CORS 预检请求失败
现象:浏览器控制台报错:
Access to XMLHttpRequest ... has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
Redirect is not allowed for a preflight request.
原因有两个:
1. CORS 配置缺少 OPTIONS 方法
NestJS 默认的 app.enableCors() 配置不够完整:
// ❌ 原始配置
app.enableCors({
origin: true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', // 缺少 OPTIONS
credentials: true,
});
修复:
// ✅ 完整 CORS 配置
app.enableCors({
origin: process.env.CORS_ORIGIN || true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
allowedHeaders: 'Content-Type,Authorization,X-Requested-With,Accept',
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
});
2. 客户端 URL 有双斜杠
请求 URL 为 https://domain.vercel.app//user/login(多了个 /),服务器会 301 重定向来规范化 URL。浏览器不允许 preflight 请求被重定向。
修复:把客户端 base URL 末尾的 / 去掉
❌ https://domain.vercel.app//user/login
✅ https://domain.vercel.app/user/login
坑四:Express 版本冲突
NestJS 11 底层使用 Express 作为 HTTP 适配器。Express 4.21+ 版本将 app.router 标记为 deprecated 并抛出 Error(不是 Warning),导致 NestFactory.create() 在 app.init() 阶段崩溃:
Error: 'app.router' is deprecated!
at ExpressAdapter.isMiddlewareApplied
解决:不需要在 package.json 中显式添加 express 依赖。@nestjs/platform-express 已经有正确的 Express 版本作为依赖。如果已经添加了,删除即可。
坑五:路径别名在 Vercel 上不工作
在 tsconfig.json 中配置的路径别名(如 "@src/*": ["src/*"])在 Vercel 的 Serverless 环境下不生效,因为 Vercel 使用 esbuild 编译且路径映射不兼容。
解决:将 src/ 开头的绝对路径改为相对路径:
// ❌ Vercel 上会报错
import { UserInfoVo } from 'src/public/vo/userInfoVo';
// ✅ 使用相对路径
import { UserInfoVo } from '../public/vo/userInfoVo';
如果需要保留别名用于本地开发,可以在 jest.config 中配置 moduleNameMapper(仅影响测试),但生产代码使用相对路径最可靠。
最终配置
src/main.ts(完整版)
import { NestFactory } from '@nestjs/core';
import { ConfigService } from '@nestjs/config';
import { AppModule } from './app.module';
import { LoggerMiddleware } from './middleware/logger/logger.middleware';
import { GlobalExceptionFilter } from './filters/global-exception.filter';
import { AutoStatusCodeInterceptor } from './filters/auto-status-code.interceptor';
import { setupGlobalValidation } from './common/pipes';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: process.env.CORS_ORIGIN || true,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
allowedHeaders: 'Content-Type,Authorization,X-Requested-With,Accept',
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
});
app.use(new LoggerMiddleware().use);
app.useGlobalFilters(new GlobalExceptionFilter());
app.useGlobalInterceptors(new AutoStatusCodeInterceptor());
setupGlobalValidation(app);
const configService = app.get(ConfigService);
const port = configService.get('PORT') || 3000;
await app.listen(port);
console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();
package.json
{
"scripts": {
"build": "nest build",
"start:dev": "nest start --watch",
"start:prod": "node dist/main"
},
"dependencies": {
"@nestjs/common": "^11.0.1",
"@nestjs/core": "^11.0.1",
"@nestjs/platform-express": "^11.0.1"
// ... 其他业务依赖
}
}
不需要
vercel.json、serverless-http、express、api/目录。
Vercel 控制台设置
| 设置项 | 值 |
|---|---|
| Framework Preset | NestJS(自动检测) |
| Build Command | npm run build(自动检测) |
| Output Directory | dist(自动检测) |
| Node.js Version | 22.x |
部署步骤
1. 确保代码干净
# 确认没有 vercel.json(除非是空项目需要特殊配置)
# 确认没有 api/ 目录
# 所有路径引用使用相对路径
git add -A
git commit -m "chore: 准备 Vercel 部署"
git push
2. 创建 Vercel 项目
# 方式一:Vercel CLI
npm i -g vercel
vercel
# 方式二:控制台导入
# 访问 https://vercel.com/new 导入 GitHub 仓库
3. 确认框架自动检测
导入后 Vercel 会自动检测 NestJS,构建日志应显示:
Detected framework: NestJS
4. 添加环境变量
在 Vercel 控制台 → Settings → Environment Variables 中添加 .env 中的所有变量。注意密码中的特殊字符需要 URL 编码(如 @ → %40)。
5. 部署
vercel --prod
总结
| 误区 | 事实 |
|---|---|
需要 vercel.json 配置 builds + routes |
Vercel 零配置原生支持 NestJS |
需要 api/index.ts + serverless-http |
不需要,src/main.ts 就是入口 |
需要显式安装 express |
@nestjs/platform-express 已包含 |
CORS 用 origin: true + methods 就够了 |
需要加 OPTIONS、allowedHeaders、preflightContinue: false |
| 改控制台 Framework Preset 就能修复 | 有缓存,重建项目才彻底 |
核心经验:Vercel 对 NestJS 的原生支持已经非常成熟,不要被网上过时的教程误导。保持项目干净、信任自动检测、确保 CORS 配置完整,就能顺利部署。
本文记录于 2026-05-28,NestJS 11 + Vercel。
参考:
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)