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

GraphQL服务本地正常但在Vercel生产环境运行异常求助

GraphQL应用部署Vercel生产环境异常排查

本地开发代码(server.js)

import { ApolloServer } from "apollo-server";
import { ApolloServerPluginLandingPageGraphQLPlayground } from "apollo-server-core";
import typeDefs from './logic/schemaGQL.js';
import mongoose from "mongoose";
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';

dotenv.config();
const MONGO_URI = process.env.DATABASE_URL;
const SECRATE = process.env.SECRATE;

mongoose.connect(MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
})

mongoose.connection.on("connected", () => {
    console.log("connected to mongodb")
})

mongoose.connection.on("error", (err) => {
    console.log("error connecting", err)
})

import './DB/User.js'
import './DB/SubWaiting.js'
import './DB/Sub.js'
import './DB/Msg.js'
import './DB/SubUncheck.js'
import './DB/Revenue.js'
import './DB/Month.js'
import './DB/PlanSold.js'
import './DB/Waiting.js'
import './DB/Refund.js'
import './DB/Help.js'

import resolvers from './logic/resolver.js'

const context = ({ req }) => {
    const { authorization } = req.headers;
    if (authorization) {
        const { userId } = jwt.verify(authorization, SECRATE)
        return { userId }
    }
}

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context,
    plugins: [
        ApolloServerPluginLandingPageGraphQLPlayground()
    ]
});

server.listen().then(({ url }) => {
    console.log(`🚀  Server ready at ${url}`);
});

Vercel生产环境代码(server.js)

import { ApolloServer } from 'apollo-server-micro';
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core';
import typeDefs from './logic/schemaGQL.js';
import mongoose from "mongoose";
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';

dotenv.config();

const MONGO_URI = process.env.DATABASE_URL;
const SECRATE = process.env.SECRATE;

mongoose.connect(MONGO_URI, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});

mongoose.connection.on("connected", () => {
    // console.log("Connected to MongoDB");
});

mongoose.connection.on("error", (err) => {
    // console.log("Error connecting to MongoDB", err);
});

import resolvers from './logic/resolver.js';

const context = ({ req }) => {
    const { authorization } = req.headers;
    if (authorization) {
        const { userId } = jwt.verify(authorization, SECRATE);
        return { userId };
    }
};

const server = new ApolloServer({
    typeDefs,
    resolvers,
    context,
    plugins: [
        ApolloServerPluginLandingPageGraphQLPlayground(),
    ],
});

// const startServer = server.start();

export default server.createHandler({
    path: '/api/graphql',
});

export const config = {
    api: {
        bodyParser: false,
    },
};

vercel.json配置

{
    "version": 2,
    "builds": [{
        "src": "server.js",
        "use": "@vercel/node"
    }],
    "routes": [{
        "src": "/api/graphql",
        "dest": "/api/graphql"
    }]
}

尝试过的路由修改

"routes": [{
    "src": "/(.*)",
    "dest": "/api"
}]

问题现象

访问 https://splits-two.vercel.app/api/graphql 时,偶尔出现404 Not Found、500 Internal Server Error,或是无服务器崩溃错误,本地运行完全正常。


可能的原因及修复方案

1. Apollo Server启动时机错误

你注释掉了server.start(),但Vercel的无服务器函数环境中,Apollo Server必须先完成启动才能处理请求。直接调用createHandler()会导致服务器未初始化就接收请求,引发500或崩溃。

修复:取消注释启动代码,改为异步等待启动完成后再处理请求:

const startServer = server.start();

export default async function handler(req, res) {
  await startServer;
  return server.createHandler({ path: '/api/graphql' })(req, res);
}

2. 环境变量未正确配置

本地用dotenv加载.env文件,但Vercel生产环境不会读取本地.env,必须在控制台手动配置DATABASE_URL和SECRATE。如果变量缺失或错误,会直接导致MongoDB连接失败、JWT验证失败,触发500错误。

修复:进入Vercel项目的「Settings -> Environment Variables」,添加这两个变量,确保值和本地一致。

3. Vercel路由配置错误

你当前的路由配置中,dest指向/api/graphql,但实际server.js是作为无服务器函数部署的,正确的dest应该指向函数文件路径/server.js。之前尝试的通配路由会把所有请求转发到/api,和你的GraphQL路径不匹配,导致404。

修复:修改vercel.json路由:

{
  "version": 2,
  "builds": [{
    "src": "server.js",
    "use": "@vercel/node"
  }],
  "routes": [{
    "src": "/api/graphql(.*)",
    "dest": "/server.js"
  }]
}

4. MongoDB连接问题

  • 旧的连接选项useNewUrlParser、useUnifiedTopology在新版本mongoose中已经是默认值,保留可能引发兼容性问题,建议移除。
  • 无服务器环境中,数据库连接随函数冷启动建立,频繁启停可能导致连接池异常,建议改用异步连接并捕获错误:

修复:

try {
  await mongoose.connect(MONGO_URI);
  console.log("Connected to MongoDB");
} catch (err) {
  console.error("MongoDB connection failed:", err);
  throw err;
}

5. Context函数的潜在报错

如果请求没有authorization头,context函数会返回undefined,依赖userId的resolver可能抛出错误,导致500。

修复:默认返回空对象或null值:

const context = ({ req }) => {
  const { authorization } = req.headers;
  if (authorization) {
    try {
      const { userId } = jwt.verify(authorization, SECRATE);
      return { userId };
    } catch (err) {
      // 处理无效token
      return { userId: null };
    }
  }
  return { userId: null };
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:17:05