前置

  • 一台 VPS(你 51testgame.com 在香港的那台)
  • 装好 Node 22 LTS、Nginx、git
  • 域名解析到服务器 IP
  • HTTPS 证书(你已经有)

流程概览

本地 git push → 服务器 git pull → npm ci + npm run build → systemctl reload
                                                  ↓
                                            Nginx 反代 :3000

第一次部署

1. 服务器装环境(CentOS)

# Node 22
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo dnf install -y nodejs

# git / nginx 应该已经有
node -v        # v22.x
nginx -v

2. 拉代码

sudo mkdir -p /var/www
sudo chown $USER:$USER /var/www
cd /var/www
git clone git@github.com:you/my-site.git
cd my-site

3. 装依赖 + 构建

npm ci                    # 干净安装(用 package-lock.json)
npm run build             # 生成 .next/ 生产构建

4. 用 systemd 跑

sudo vim /etc/systemd/system/my-site.service
[Unit]
Description=My Site (Next.js)
After=network.target

[Service]
Type=simple
User=wadely
WorkingDirectory=/var/www/my-site
ExecStart=/usr/bin/npm run start
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
Environment=PORT=3000

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now my-site
sudo systemctl status my-site

确认监听 :3000:

ss -tlnp | grep 3000
curl http://localhost:3000

5. Nginx 反代

/etc/nginx/conf.d/my-site.conf:

server {
    listen 80;
    server_name 51testgame.com www.51testgame.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name 51testgame.com www.51testgame.com;

    ssl_certificate     /etc/letsencrypt/live/51testgame.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/51testgame.com/privkey.pem;

    gzip on;
    gzip_types text/plain text/css application/javascript application/json image/svg+xml;

    # 静态资源长缓存
    location /_next/static/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }
    location /static/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }

    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";
    }
}
sudo nginx -t && sudo systemctl reload nginx

打开 https://51testgame.com 看到 Next.js 站点 = 成功。

后续部署(更新代码)

写一个 deploy.sh 放在服务器:

#!/bin/bash
set -e

cd /var/www/my-site
git pull
npm ci --omit=dev          # 生产装依赖(不装 devDeps)
npm install --no-save --include=dev  # 装构建用的 devDeps
npm run build
sudo systemctl restart my-site

echo "✓ Deployed at $(date)"
chmod +x deploy.sh

之后:

ssh wadely@51testgame.com '/var/www/my-site/deploy.sh'

用 GitHub Actions 自动部署

.github/workflows/deploy.yml:

name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.DEPLOY_KEY }}
      - name: Deploy
        run: |
          ssh -o StrictHostKeyChecking=no wadely@${{ secrets.SERVER_IP }} \
              '/var/www/my-site/deploy.sh'

仓库 Settings → Secrets and variables → Actions 加:

  • DEPLOY_KEY:服务器的 deploy 私钥
  • SERVER_IP:51testgame.com 的 IP

之后 git push 自动部署。

环境变量

.env.production不进 git):

DATABASE_URL=postgresql://...
NEXTAUTH_SECRET=xxx

或 systemd unit 里:

Environment=DATABASE_URL=postgresql://...
EnvironmentFile=/etc/my-site/env

/etc/my-site/env:

DATABASE_URL=postgresql://...
sudo chmod 600 /etc/my-site/env       # 限制权限
sudo chown wadely:wadely /etc/my-site/env

用 PM2 替代 systemd

如果觉得 systemd 麻烦:

npm install -g pm2
cd /var/www/my-site
pm2 start npm --name my-site -- start
pm2 save
pm2 startup           # 配开机自启(按提示一行命令)

更新部署:

git pull
npm ci && npm run build
pm2 reload my-site         # 零停机重启

性能优化

1. 启用 Next.js standalone 输出

next.config.ts:

const config = {
    output: 'standalone',
};

npm run build 后生成 .next/standalone/ —— 只包含必要文件,部署体积减半。

启动改成:

node .next/standalone/server.js

2. 多实例(cluster)

pm2 start npm --name my-site -i max -- start    # 按 CPU 核数起

或 systemd 多 unit + Nginx upstream 负载均衡。

3. CDN 加速

国内访问:

  • 静态资源(/_next/static/*)放到对象存储 + CDN(阿里 OSS / 腾讯 COS)
  • next.config.tsassetPrefix
const config = {
    assetPrefix: process.env.NODE_ENV === 'production' ? 'https://cdn.51testgame.com' : '',
};

监控

# 看日志
sudo journalctl -u my-site -f          # systemd
pm2 logs my-site                        # pm2

# 看资源
sudo systemctl status my-site
top -p $(pgrep -f "next start")

  • 内存不够大的 VPS(1G)build 时 OOM——加 swap 或在本地 build 再 rsync
  • npm ci --omit=dev 不装 devDeps 但 build 需要——分两步装
  • Server Action 提交大 body → Nginx 配置 client_max_body_size 50M
  • 改了 .env必须重启服务——Next.js 启动期读取

至此 17 篇 react-quick 完成。下一步去 react-advanced 系列深入 React。