将Next.js应用部署到Vercel后后端API无法正常工作的解决方法
我通过GitHub将Next.js应用部署到Vercel平台,部署前已配置.env文件中的环境变量。我使用自定义的server.js文件启动服务,采用node server.js脚本而非next start命令。
package.json中的scripts配置如下:
"scripts": { "start": "node server", "dev": "next dev", "build": "next build", "serve": "next start", "lint": "next lint" }
server.js文件内容如下:
const express = require('express'); const https = require('https'); const fs = require('fs'); const next = require('next'); const dotenv = require("dotenv"); const morgan = require("morgan"); const bodyParser = require('body-parser'); const cors = require("cors"); const path = require('path'); const connectToMongodb = require('./src/db/mongodb'); dotenv.config({ path: "./.env" }); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); console.log('started') app.prepare().then(() => { const server = express(); server.use(morgan('dev')) server.use(express.json()); server.use(cors()); server.use(bodyParser.json()); server.use(express.static(path.join(__dirname, 'public'))) const options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') }; console.error('before connecting...') connectToMongodb(); console.error('after connecting...') console.log('after connecting...') server.all('*', (req, res) => { return handle(req, res); }); https.createServer(options, server).listen(443, () => { console.log('Server running on https://localhost'); }); });
部署到Vercel时无需创建HTTPS服务器,部署启动后前端功能正常,但后端无法工作,推测Vercel Serverless Function无法处理传入的API请求,请问该如何修复以让后端正常运行?
1. 适配Vercel部署模型,放弃自定义server.js启动方式
Vercel的Next.js部署默认采用自身托管机制,不支持自定义Express服务器作为入口(除非使用Vercel的Serverless Functions或Edge Functions)。你的自定义server.js在本地可运行,但部署到Vercel时,平台会忽略start脚本,直接用Next.js内置服务处理请求,导致Express中间件和数据库连接逻辑无法生效。
具体调整:
- 修改
package.json的start脚本为next start,让Vercel使用标准启动流程:
"start": "next start"
- 删除
server.js中的HTTPS服务器创建代码,Vercel会自动处理HTTPS,本地开发可通过next dev或反向代理实现HTTPS,无需手动配置证书。
2. 迁移API路由到Next.js内置API Routes
Vercel对Next.js的API Routes有原生支持,这是在Vercel上运行后端逻辑的标准方式。需将server.js中的后端逻辑(数据库连接、中间件等)迁移到pages/api目录下的文件中:
步骤:
- 在项目根目录创建
pages/api文件夹(若不存在)。 - 将原API逻辑拆分为单个文件,比如
pages/api/users.js处理用户相关请求。 - 在API路由文件中引入数据库连接和中间件:
import connectToMongodb from '../../src/db/mongodb'; import cors from 'cors'; import morgan from 'morgan'; import express from 'express'; const app = express(); app.use(morgan('dev')); app.use(cors()); app.use(express.json()); // 连接数据库(可封装为全局中间件) connectToMongodb(); export default app;
Next.js API Routes默认支持Express风格中间件,直接导出处理函数或Express实例即可。
3. 配置环境变量
Vercel不会自动读取GitHub仓库中的.env文件,需在平台项目设置中手动添加环境变量:
- 进入Vercel项目的Settings -> Environment Variables
- 添加
.env中的所有键值对,例如MONGODB_URI等。
4. 优化数据库连接逻辑
Vercel的Serverless环境中,需避免每次请求创建新数据库连接,添加连接缓存逻辑:
import mongoose from 'mongoose'; let cachedDb = null; async function connectToMongodb() { if (cachedDb) { return cachedDb; } const db = await mongoose.connect(process.env.MONGODB_URI); cachedDb = db; return db; } export default connectToMongodb;
此逻辑可复用连接,避免Serverless环境下连接数过多问题。
5. 测试部署
完成调整后,重新推送代码到GitHub触发Vercel自动部署,测试API路由是否正常工作。
内容的提问来源于stack exchange,提问作者toygr

