# 部署文档 ## 项目概览 **技术栈:** Nuxt 4 + Nuxt UI + Pinia + ofetch **构建产物:** SSR 模式,生成 `.output` 目录(包含 Node.js 服务器) --- ## 一、构建前准备 ### 1.1 环境变量配置 复制 `.env.example` 为 `.env`: ```bash cp .env.example .env ``` 编辑 `.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 安装依赖并构建 ```bash # 安装依赖 pnpm install # 构建生产版本 pnpm run build ``` 构建产物位于 `.output/` 目录: ``` .output/ ├── public/ # 静态资源 ├── server/ # Node.js 服务器 │ └── index.mjs # 入口文件 └── server/ └── index.mjs ``` ### 2.2 本地预览 ```bash # 构建后本地测试 pnpm run preview ``` --- ## 三、部署方案 ### 方案 1:直接部署(推荐) **适用场景:** 支持 SSR 的服务器环境 **启动命令:** ```bash # 设置环境变量 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 管理进程:** ```bash # 安装 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):** ```javascript 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 } }] } ``` 使用配置文件启动: ```bash pm2 start ecosystem.config.js ``` --- ### 方案 2:Docker 部署 **Dockerfile:** ```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:** ```yaml 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 ``` **构建和启动:** ```bash # 构建镜像 docker compose build # 启动服务 docker compose up -d # 查看日志 docker compose logs -f # 停止服务 docker compose down ``` --- ### 方案 3:Nginx 反向代理 **适用场景:** 生产环境,配合 Nginx 使用 **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): ```typescript 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 默认内存限制 **解决:** ```bash node --max-old-space-size=4096 .output/server/index.mjs ``` --- ## 七、生产环境检查清单 - [ ] 环境变量已正确配置 - [ ] 后端 API 地址正确 - [ ] SSL 证书已配置(HTTPS) - [ ] Nginx 反向代理已配置 - [ ] Gzip 压缩已启用 - [ ] 静态资源缓存策略已设置 - [ ] 进程管理工具已配置(PM2/Docker) - [ ] 错误监控已配置(可选) --- ## 八、监控和日志 ### 8.1 PM2 日志 ```bash # 实时日志 pm2 logs binglogy-blog --lines 100 # 错误日志 pm2 logs binglogy-blog --err # 日志文件位置 ~/.pm2/logs/ ``` ### 8.2 Docker 日志 ```bash # 实时日志 docker logs -f binglogy-blog # 最近100行 docker logs --tail 100 binglogy-blog ``` ### 8.3 Nginx 日志 ```bash # 访问日志 tail -f /var/log/nginx/access.log # 错误日志 tail -f /var/log/nginx/error.log ```