Nuxt 4 部署指南:Node、Nginx 与 PM2 的生产配置

从 Nuxt 4 构建产物、运行时环境变量、PM2 守护进程到 Nginx 反向代理,完整梳理一套适合普通云服务器的生产部署流程。

Nuxt 4 部署指南:Node、Nginx 与 PM2 的生产配置

Nuxt 4 默认可以构建成 Nitro Node 服务。它不是把 dist 目录交给 Nginx 就结束,而是由 Node 执行服务端渲染,再由 Nginx 负责域名、HTTPS、压缩和反向代理。

部署链路

text
浏览器 -> Nginx :443 -> Nuxt Nitro :3000 -> 后端 API

Nginx 是公网入口,Nuxt 只监听本机地址。这样既能保留 SSR,也避免直接暴露 Node 端口。

第一步:构建

bash
pnpm install --frozen-lockfile
pnpm build

默认 Node server preset 的入口是:

text
.output/server/index.mjs

部署时至少需要完整上传 .output。不要只上传 .output/public,否则服务端路由和 SSR 都无法运行。构建机器与服务器架构差异较大时,最好在目标服务器或一致的 CI 容器中构建。

第二步:先直接启动验证

bash
NODE_ENV=production \
HOST=127.0.0.1 \
PORT=3000 \
NUXT_PUBLIC_API_BASE=https://www.example.com/app-api \
NUXT_PUBLIC_SITE_URL=https://www.example.com \
node .output/server/index.mjs

Nuxt 的 Node 服务支持 PORTNITRO_PORT,以及 HOSTNITRO_HOST。生产环境建议显式设置 NODE_ENV=production,避免开发警告进入日志。

验证本机服务:

bash
curl -I http://127.0.0.1:3000/
curl http://127.0.0.1:3000/robots.txt

先确认 Node 服务正常,再配置 Nginx。这样出现 502 时容易判断是进程未启动,还是代理配置错误。

第三步:使用 PM2 守护

小内存服务器不要直接使用 instances: 'max',否则每个实例都会占用一份内存。博客流量不高时单实例更稳妥:

js
// ecosystem.config.cjs
module.exports = {
  apps: [{
    name: 'lemon-blog',
    script: './.output/server/index.mjs',
    instances: 1,
    exec_mode: 'fork',
    max_memory_restart: '350M',
    env: {
      NODE_ENV: 'production',
      HOST: '127.0.0.1',
      PORT: '3000',
      NUXT_PUBLIC_API_BASE: 'https://www.example.com/app-api',
      NUXT_PUBLIC_SITE_URL: 'https://www.example.com',
    },
  }],
}
bash
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup

pm2 startup 会输出一条需要执行的系统命令。完成后,服务器重启才会自动恢复进程。

第四步:Nginx 反向代理

nginx
server {
    listen 443 ssl http2;
    server_name www.example.com;

    client_max_body_size 32m;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    location /app-api/ {
        proxy_pass http://127.0.0.1:48090/app-api/;
        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;
    }
}

修改后先测试再重载:

bash
nginx -t
nginx -s reload

如果使用宝塔,应在对应网站配置中修改,并保留面板生成的 SSL 证书路径。

发布更新的安全顺序

  1. 在新目录上传并解压构建产物。
  2. 检查环境变量和文件权限。
  3. 使用临时端口启动并访问首页。
  4. 切换软链接或替换当前版本目录。
  5. 执行 pm2 reload lemon-blog
  6. 检查首页、文章详情、接口、robots 和 sitemap。
  7. 保留上一版产物,方便快速回滚。

502 与页面异常排查

现象 优先检查
Nginx 502 PM2 状态、3000 端口、Node 日志
页面无样式 .output/public 是否完整、代理路径是否被重写
API 地址仍是本地 运行时变量名、PM2 重启、public 配置声明
刷新动态路由 404 请求是否真的进入 Nuxt,而不是静态目录
内存持续增长 PM2 内存、日志量、缓存与接口响应大小

常用诊断命令:

bash
pm2 status
pm2 logs lemon-blog --lines 100
ss -lntp | grep 3000
curl -I http://127.0.0.1:3000/articles/example

小结

可靠部署的关键是把每一层分开验证:先构建产物,再验证 Node,随后接入 PM2,最后配置 Nginx。遇到问题时沿着浏览器、Nginx、Nuxt、API 的链路逐层检查,比反复重装依赖更有效。

参考:Nuxt 4 Deployment 官方文档