397 lines
7.4 KiB
Markdown
397 lines
7.4 KiB
Markdown
# 部署文档
|
||
|
||
## 项目概览
|
||
|
||
**技术栈:** 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
|
||
```
|