397 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 部署文档
## 项目概览
**技术栈:** 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
```
---
### 方案 2Docker 部署
**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
```
---
### 方案 3Nginx 反向代理
**适用场景:** 生产环境,配合 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
```