7.4 KiB
Raw Permalink Blame History

部署文档

项目概览

技术栈: Nuxt 4 + Nuxt UI + Pinia + ofetch

构建产物: SSR 模式,生成 .output 目录(包含 Node.js 服务器)


一、构建前准备

1.1 环境变量配置

复制 .env.example.env

cp .env.example .env

编辑 .env 文件:

# API 后端地址
NUXT_PUBLIC_API_BASE=https://api.yourdomain.com

# 站点地址
NUXT_PUBLIC_SITE_URL=https://yourdomain.com
NUXT_PUBLIC_SITE_NAME=LinkShare Blog

二、构建应用

2.1 安装依赖并构建

# 安装依赖
pnpm install

# 构建生产版本
pnpm run build

构建产物位于 .output/ 目录:

.output/
├── public/          # 静态资源
├── server/          # Node.js 服务器
│   └── index.mjs   # 入口文件
└── server/
    └── index.mjs

2.2 本地预览

# 构建后本地测试
pnpm run preview

三、部署方案

方案 1直接部署推荐

适用场景: 支持 SSR 的服务器环境

启动命令:

# 设置环境变量
export NUXT_PUBLIC_API_BASE="https://api.yourdomain.com"
export NUXT_PUBLIC_SITE_URL="https://yourdomain.com"
export NUXT_PUBLIC_SITE_NAME="LinkShare Blog"

# 启动服务器
node .output/server/index.mjs

使用 PM2 管理进程:

# 安装 PM2
npm install -g pm2

# 启动应用
pm2 start .output/server/index.mjs --name "binglogy-blog" -- \
  --env production

# 查看状态
pm2 status

# 查看日志
pm2 logs binglogy-blog

# 设置开机自启
pm2 save
pm2 startup

PM2 配置文件ecosystem.config.js

module.exports = {
  apps: [{
    name: 'binglogy-blog',
    script: '.output/server/index.mjs',
    instances: 'max',
    exec_mode: 'cluster',
    env: {
      NODE_ENV: 'production',
      NUXT_PUBLIC_API_BASE: 'https://api.yourdomain.com',
      NUXT_PUBLIC_SITE_URL: 'https://yourdomain.com',
      NUXT_PUBLIC_SITE_NAME: 'LinkShare Blog',
      PORT: 3000
    }
  }]
}

使用配置文件启动:

pm2 start ecosystem.config.js

方案 2Docker 部署

Dockerfile

# 构建阶段
FROM node:20-alpine AS builder

WORKDIR /app

# 安装 pnpm
RUN npm install -g pnpm

# 安装依赖
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# 构建应用
COPY . .
RUN pnpm run build

# 生产阶段
FROM node:20-alpine

WORKDIR /app

# 设置环境变量
ENV NODE_ENV=production

# 复制构建产物
COPY --from=builder /app/.output ./.output
COPY --from=builder /app/public ./public

# 暴露端口
EXPOSE 3000

# 启动服务器
CMD ["node", ".output/server/index.mjs"]

docker-compose.yml

version: '3.8'

services:
  frontend:
    build: .
    container_name: binglogy-blog
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - NUXT_PUBLIC_API_BASE=https://api.yourdomain.com
      - NUXT_PUBLIC_SITE_URL=https://yourdomain.com
      - NUXT_PUBLIC_SITE_NAME=LinkShare Blog
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - binglogy

networks:
  binglogy:
    driver: bridge

构建和启动:

# 构建镜像
docker compose build

# 启动服务
docker compose up -d

# 查看日志
docker compose logs -f

# 停止服务
docker compose down

方案 3Nginx 反向代理

适用场景: 生产环境,配合 Nginx 使用

Nginx 配置:

server {
    listen 80;
    server_name yourdomain.com;

    # HTTPS 重定向
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # SSL 证书
    ssl_certificate /etc/nginx/ssl/yourdomain.com.pem;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;

    # 静态资源缓存
    location /_nuxt/ {
        alias /path/to/.output/public/_nuxt/;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 其他静态文件
    location /static/ {
        alias /path/to/.output/public/static/;
        expires 30d;
        add_header Cache-Control "public";
    }

    # 代理到 Nuxt
    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;
    }

    # 错误页面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}

四、路由规则配置

项目已配置以下路由规则nuxt.config.ts

nitro: {
  routeRules: {
    '/': { isr: 60 },           // 首页每60秒重新验证
    '/article/**': { isr: 300 }, // 文章页每300秒重新验证
    '/admin/**': { ssr: false }, // 管理后台纯客户端渲染
  },
}

五、环境变量说明

变量名 说明 默认值 必填
NUXT_PUBLIC_API_BASE 后端 API 地址 http://localhost:3001
NUXT_PUBLIC_SITE_URL 站点 URL http://localhost:3000
NUXT_PUBLIC_SITE_NAME 站点名称 LinkShare Blog
PORT 服务端口 3000

六、常见问题

6.1 启动报错 "Cannot find module"

原因: 构建产物未正确复制

解决: 确保 .output 目录完整,运行 pnpm run build 重新构建

6.2 API 请求跨域

原因: 后端 CORS 配置不正确

解决: 后端需允许前端域名,建议使用 Nginx 反向代理,前端和后端同源

6.3 页面加载慢

原因: SSR 首次渲染较慢

解决:

  • 调整 ISR 缓存时间nuxt.config.ts 中的 routeRules
  • 使用 CDN 加速静态资源
  • 启用 Nginx Gzip 压缩

6.4 内存占用过高

原因: Node.js 默认内存限制

解决:

node --max-old-space-size=4096 .output/server/index.mjs

七、生产环境检查清单

  • 环境变量已正确配置
  • 后端 API 地址正确
  • SSL 证书已配置HTTPS
  • Nginx 反向代理已配置
  • Gzip 压缩已启用
  • 静态资源缓存策略已设置
  • 进程管理工具已配置PM2/Docker
  • 错误监控已配置(可选)

八、监控和日志

8.1 PM2 日志

# 实时日志
pm2 logs binglogy-blog --lines 100

# 错误日志
pm2 logs binglogy-blog --err

# 日志文件位置
~/.pm2/logs/

8.2 Docker 日志

# 实时日志
docker logs -f binglogy-blog

# 最近100行
docker logs --tail 100 binglogy-blog

8.3 Nginx 日志

# 访问日志
tail -f /var/log/nginx/access.log

# 错误日志
tail -f /var/log/nginx/error.log