next.js启用custom server后需用nginx反向代理并分离静态资源与动态请求:静态文件(/_next/static/、/static/等)由nginx直接服务,/api/、/_next/动态部分及ssr页面代理至node服务,须配置proxy_http_version 1.1、upgrade头和合理超时。

Next.js 默认使用静态导出或内置开发服务器,但若启用 Custom Server(如用 express、koa 或原生 http 启动),它就变成一个常规的 Node.js 后端服务 —— 此时 Nginx 不再只作静态文件代理,而需承担反向代理、路由分发、HTTPS 终止、负载均衡等职责。配置不当会导致 502 Bad Gateway、静态资源 404、API 路由失效、WebSocket 断连等问题。
核心原则:Nginx 是入口网关,Node 进程是后端应用
Custom Server 启动后监听某个本地端口(如 3000),不处理静态文件(Next.js 已将 .next/static 和 public/ 目录暴露为可访问路径),也不做 SSR 请求路由判断 —— 这些都交给 Nginx 提前拦截或透传。关键点:
- Nginx 必须显式代理所有非静态资源请求到 Node 服务(包括
/api/、/_next/动态部分、SSR 页面) - 静态资源(
/static/、/_next/static/、/favicon.ico等)应由 Nginx 直接提供,不打到 Node - 必须启用
proxy_http_version 1.1和proxy_set_header Upgrade,否则getServerSideProps或 WebSocket 会失败 - 超时设置要合理:
proxy_read_timeout 60(SSR 渲染可能耗时较长)
基础 Nginx 配置(支持 SSR + API + 静态资源)
假设 Next.js Custom Server 运行在 localhost:3000,构建产物位于 /var/www/my-next-app:
server {
listen 80;
server_name example.com;
<pre class="brush:php;toolbar:false;"># 静态资源:优先由 Nginx 服务
location ^~ /_next/static/ {
alias /var/www/my-next-app/.next/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
location ^~ /static/ {
alias /var/www/my-next-app/public/static/;
expires 1y;
}
location = /favicon.ico {
alias /var/www/my-next-app/public/favicon.ico;
expires 1y;
}
# Next.js 内置路径(如 /_next/webpack-hmr)需透传给 Node
location ^~ /_next/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 60;
}
# API 路由和所有动态页面(SSR/ISR)全部代理
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 60;
}}
⚠️ 注意:location / 必须放在最后,否则会覆盖上面更精确的 ^~ /_next/static/ 规则;^~ 表示前缀匹配且不参与正则竞争,比 location ~ \.js$ 更高效安全。
进阶:区分 SSR 页面与静态生成(SSG)页面
如果你混合使用 SSG(getStaticProps)和 SSR(getServerSideProps),可让 Nginx 缓存已预生成的 HTML 页面,减少 Node 压力:
- Next.js 构建后,SSG 页面会输出为
.next/server/pages/*.html(App Router 下为.next/server/app/*的index.html) - 在 Nginx 中添加规则,对已存在的 SSG HTML 文件直接返回(需配合
try_files) - 示例(放在
location /内):try_files $uri $uri/index.html @node; location @node { proxy_pass http://127.0.0.1:3000; # ... 其他 proxy_* 设置 } - 该方式要求构建产物结构清晰,且不依赖运行时数据 —— 否则缓存会返回过期内容
常见问题速查与修复
-
502 Bad Gateway:检查 Node 进程是否运行(
curl http://127.0.0.1:3000)、端口是否被防火墙拦截、proxy_pass地址是否拼写错误 -
JS/CSS 404:确认
/_next/static/路径下文件真实存在;检查alias末尾是否多写了斜杠(alias /path/;正确,alias /path;错误) -
API 返回 404:Custom Server 是否正确挂载了
/api路由?Nginx 是否把/api/xxx错误地匹配到了静态规则?建议加location ^~ /api/ { proxy_pass ... }显式代理 -
刷新页面白屏或重定向异常:检查
X-Forwarded-Proto和X-Forwarded-For是否透传,Next.js 中getServerSideProps读取 URL 时依赖这些头










