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

NextJS自定义服务器执行npm run build构建后出现CORS错误

解决Next.js SSR生产构建后认证失效与CORS拦截问题

我来帮你梳理下问题根源和解决方案,你遇到的情况其实是两个关键点没处理好:生产环境下的代理缺失,以及CORS配置的细节冲突。

问题核心分析

  1. 开发vs生产的代理差异:你的自定义服务器代码里,只有isDevelopment为true时才启用了http-proxy-middleware代理。开发时前端请求/api会被转发到后端5002端口,属于同域请求(都是从3000端口发起),所以Cookie能正常传递,也不会有CORS问题。但生产构建后,代理没启用,前端直接请求localhost:5002,这就产生了跨域,加上你开启了withCredentials: true,而后端如果配置的是Access-Control-Allow-Origin: *,就会触发浏览器的CORS拦截规则——带凭证的请求不允许使用通配符源。

  2. CORS配置的冲突:当请求携带凭证(Cookie、HTTP认证等)时,后端的CORS必须满足两个条件:

    • Access-Control-Allow-Origin不能是*,必须是前端的具体源(比如http://localhost:3000)
    • 必须设置Access-Control-Allow-Credentials: true

解决方案一:生产环境启用代理(推荐)

既然你用了自定义服务器,最好保持开发和生产环境的请求一致,都通过代理转发,这样从根源上避免跨域问题。修改你的server.js代码,去掉代理的环境判断:

const express = require('express');
const next = require('next');
const { createProxyMiddleware } = require('http-proxy-middleware');
const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const apiPaths = {
  '/api': {
    target: 'http://localhost:5002',
    pathRewrite: {
      '^/api': '/api',
    },
    changeOrigin: true,
    // 可选:如果后端需要识别真实客户端IP,开启此项
    // xfwd: true
  },
};

app
  .prepare()
  .then(() => {
    const server = express();
    // 移除环境判断,生产环境也启用代理
    server.use('/api', createProxyMiddleware(apiPaths['/api']));
    
    server.all('*', (req, res) => {
      return handle(req, res);
    });
    server.listen(port, (err) => {
      if (err) throw err;
      console.log(`> Ready on http://localhost:${port}`);
    });
  })
  .catch((err) => {
    console.log('Error:::::', err);
  });

修改后,生产环境下前端请求/api会被服务器转发到5002端口,属于同域请求,你甚至可以把Axios里的withCredentials: true去掉(因为不需要跨域传凭证了),Cookie会自动在服务器转发时传递给后端。

解决方案二:正确配置后端CORS(不推荐,仅当无法使用代理时)

如果一定要让前端直接请求5002端口,需要调整后端的CORS配置:

后端Express的cors配置修改

const cors = require('cors');

// 配置允许的源,生产环境要换成你的实际域名
const allowedOrigins = ['http://localhost:3000'];

const corsOptions = {
  origin: function (origin, callback) {
    // 允许没有origin的请求(比如Postman)或者在允许列表里的源
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true // 必须设置为true,允许传递凭证
};

app.use(cors(corsOptions));

前端Axios配置保持

确保你的Axios请求里的withCredentials: true保留,同时请求的URL要正确指向5002端口(或者你的后端域名)。

额外注意点

  • 生产环境部署时,记得把allowedOrigins里的localhost:3000换成你的实际前端域名,比如https://your-app.com。
  • 如果你用了Next.js的SSG/ISR,要确保获取数据的逻辑在getServerSideProps里执行,这样服务器端请求后端不会有跨域问题,也能直接传递Cookie。

内容的提问来源于stack exchange,提问作者Abu Sayeed Mondal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 16:54:08