npm run build
构建完成后,生成的文件在 dist/ 目录下。
# 安装依赖
npm install
# 构建生产版本
npm run build
server {
listen 80;
server_name example.com;
root /path/to/dist;
index index.html;
# Vue Router 历史模式支持
location / {
try_files $uri $uri/ /index.html;
}
# API 代理
location /api {
proxy_pass http://backend:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 静态资源缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript
application/x-javascript application/xml+rss
application/javascript application/json;
}
创建 .env.production 文件:
# 生产环境配置
VITE_API_URL=https://api.example.com
VITE_PUBLIC_PATH=/
VITE_PORT=443
VITE_OUTPUT_DIR=dist
FROM node:16-alpine AS builder
WORKDIR /app
# 复制依赖文件
COPY package*.json ./
# 安装依赖
RUN npm ci
# 复制源代码
COPY . .
# 构建
RUN npm run build
# 生产环境
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
version: '3.8'
services:
web:
build: .
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- backend
restart: unless-stopped
backend:
image: django-backend:latest
ports:
- "8000:8000"
environment:
- DATABASE_URL=mysql://user:password@db:3306/dbname
depends_on:
- db
restart: unless-stopped
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=dbname
volumes:
- mysql_data:/var/lib/mysql
restart: unless-stopped
volumes:
mysql_data:
docker-compose up -d
支持阿里云 OSS、腾讯云 COS、AWS S3 等。
# 安装工具(以阿里云 OSS 为例)
npm install -g ossutil
# 同步文件
ossutil cp -r dist/ oss://bucket-name/
.env.development
VITE_API_URL=http://localhost:8000
VITE_PUBLIC_PATH=/
VITE_PORT=8080
.env.production
VITE_API_URL=https://api.example.com
VITE_PUBLIC_PATH=/
VITE_PORT=443
.env.local_prod
VITE_API_URL=http://localhost:8000
VITE_PUBLIC_PATH=/
VITE_PORT=8080
# 用户
user nginx;
# 工作进程数
worker_processes auto;
# 错误日志
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# 基本设置
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
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;
# 服务器配置
server {
listen 80;
server_name example.com;
root /usr/share/nginx/html;
index index.html;
# 网站根目录
location / {
try_files $uri $uri/ /index.html;
}
# API 代理
location /api {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 静态资源
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 其他配置同 HTTP
}
}
# 安装 certbot
sudo apt-get install certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d example.com
# 自动续期
sudo certbot renew --dry-run
listen 443 ssl http2;
见 Nginx 配置示例
location ~* \.(js|css)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
Vite 已自动配置代码分割,生产环境会自动生成多个 chunk。
vite.config.ts 中的 base 配置VITE_PUBLIC_PATH 配置try_files $uri $uri/ /index.html;# Nginx 访问日志
tail -f /var/log/nginx/access.log
# Nginx 错误日志
tail -f /var/log/nginx/error.log
# 系统日志
journalctl -u nginx -f
# 拉取最新代码
git pull origin master
# 安装新依赖
npm install
# 重新构建
npm run build
# 重启服务
sudo systemctl restart nginx
# 切换到旧版本
git checkout v1.0.0
# 重新构建
npm run build
# 重启服务
sudo systemctl restart nginx
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 页面白屏 | JS 文件路径错误 | 检查 VITE_PUBLIC_PATH 配置 |
| API 404 | 后端服务未启动 | 启动后端服务 |
| 静态资源 404 | 文件权限问题 | chmod 755 静态文件 |
| 路由刷新 404 | Nginx 配置错误 | 检查 try_files 配置 |
| CORS 错误 | 跨域配置错误 | 配置后端 CORS |
| 登录失败 | Token 验证失败 | 检查 JWT 配置 |
name: Deploy
on:
push:
branches: [ master ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
- name: Deploy to server
uses: easingthemes/ssh-deploy@v2
with:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
ARGS: "-rltgoDzvO"
SOURCE: "dist/"
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
REMOTE_USER: ${{ secrets.REMOTE_USER }}
TARGET: "/var/www/html/"
部署注意事项: