1. 项目概述
在Web应用开发中,我们经常需要将前后台系统部署在同一个域名下。这种部署方式既能节省域名资源,又能简化运维管理。但如何通过路径区分前后台访问,同时处理好静态资源、API代理和前端路由等问题,就需要对Nginx进行精细配置。
我最近在部署一个Java+Vue的全栈项目时,就遇到了这样的需求。前台面向普通用户,后台供管理员使用,两者需要共享同一个域名。经过多次实践和调试,最终形成了一套可靠的配置方案。本文将详细介绍如何通过Nginx的路径匹配规则,实现前后台系统的同域名部署。
2. Nginx核心配置解析
2.1 基础服务器配置
首先来看Nginx的基础服务器配置。我们需要定义一个server块,监听80端口(HTTP)或443端口(HTTPS),并指定服务器域名:
nginx复制server {
listen 80;
server_name example.com; # 替换为你的实际域名
root /usr/share/nginx/html;
# 其他配置将在这里添加
}
提示:如果是生产环境,强烈建议配置HTTPS。可以使用Let's Encrypt免费证书,通过Certbot工具自动配置。
2.2 前台静态资源配置
前台系统通常部署在根路径下。我们使用location /来匹配所有请求,并指定前台静态文件的存放目录:
nginx复制location / {
root /usr/share/nginx/html/client;
index index.html;
try_files $uri $uri/ /index.html;
}
关键点解析:
root指令指定了前台静态文件的根目录try_files指令用于支持Vue Router的history模式,确保页面刷新不出现404index指令指定默认访问的文件是index.html
2.3 后台静态资源配置
后台系统我们部署在/manger路径下(注意:实际项目中建议使用更安全的路径名,如/admin):
nginx复制location /manger {
alias /usr/share/nginx/html/manger;
index index.html;
try_files $uri $uri/ /manger/index.html;
}
这里有几个重要区别:
- 使用
alias而非root指令,因为路径映射不是简单的目录拼接 - try_files的fallback路径要包含/manger前缀
- 路径名必须与前端配置完全一致
2.4 API请求代理配置
前后台系统都需要访问后端API,我们统一通过/prod-api路径代理:
nginx复制location /prod-api/ {
proxy_pass http://backend:8080/;
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_pass末尾的斜杠/必须保留,否则Nginx会将/prod-api前缀也传递给后端服务。
3. 目录结构与部署准备
3.1 推荐目录结构
合理的目录结构能让部署更加清晰。以下是建议的部署目录结构:
code复制/usr/share/nginx/html/
├── client/ # 前台静态资源
│ ├── css/
│ ├── js/
│ ├── img/
│ └── index.html
├── manger/ # 后台静态资源
│ ├── css/
│ ├── js/
│ ├── img/
│ └── index.html
└── nginx.conf # Nginx配置文件
3.2 部署前检查清单
- 确保所有静态文件已构建完成(Vue项目执行npm run build)
- 检查文件权限:Nginx用户(通常是nginx或www-data)需要有读取权限
- 确认后端服务正常运行且可访问
- 测试各路径是否按预期工作:
- / 应返回前台首页
- /manger 应返回后台登录页
- /prod-api/health 应返回后端健康检查结果
4. 前端项目配置详解
4.1 Vue后台项目配置
后台项目需要特殊配置以匹配Nginx的/manger路径:
- vue.config.js配置:
javascript复制module.exports = {
publicPath: process.env.NODE_ENV === 'production' ? '/manger' : '/',
outputDir: 'dist/manger',
// 其他配置...
}
- 路由配置:
javascript复制const router = new VueRouter({
base: '/manger',
mode: 'history',
routes
})
4.2 前台API请求配置
使用axios实例配置统一的API前缀:
javascript复制const api = axios.create({
baseURL: '/prod-api',
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})
// 请求拦截器示例
api.interceptors.request.use(config => {
const token = store.getters.token
if (token) {
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
5. 常见问题与解决方案
5.1 页面刷新出现404
问题原因:Vue Router的history模式需要服务器配合,直接刷新页面时,服务器会尝试查找对应的文件路径。
解决方案:
- 确保Nginx配置中包含try_files指令
- 检查try_files的fallback路径是否正确
- 前后台项目的base路径必须与Nginx配置一致
5.2 API请求返回404
排查步骤:
- 检查proxy_pass地址是否正确
- 确认后端服务是否健康运行
- 使用curl直接测试后端接口是否可用
- 检查Nginx错误日志:/var/log/nginx/error.log
5.3 静态资源加载失败
常见原因:
- 文件路径大小写不匹配(Linux系统区分大小写)
- 文件权限问题(Nginx用户无读取权限)
- 构建时publicPath配置错误
解决方法:
bash复制# 检查文件权限
sudo chown -R nginx:nginx /usr/share/nginx/html
sudo chmod -R 755 /usr/share/nginx/html
# 检查Nginx配置
sudo nginx -t
sudo systemctl restart nginx
6. 高级配置与优化建议
6.1 启用Gzip压缩
在Nginx配置中添加gzip压缩,减少传输体积:
nginx复制gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1k;
gzip_comp_level 6;
gzip_vary on;
6.2 静态资源缓存策略
为静态资源设置长期缓存,利用浏览器缓存提高性能:
nginx复制location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
6.3 安全加固建议
- 隐藏Nginx版本信息:
nginx复制server_tokens off;
- 限制敏感路径访问:
nginx复制location ^~ /manger {
# 添加IP限制或HTTP Basic认证
allow 192.168.1.0/24;
deny all;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
- 配置安全头部:
nginx复制add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
7. 实际部署经验分享
在实际部署过程中,我总结了以下几点经验:
-
路径一致性是关键:前端项目的publicPath、路由base、API baseURL必须与Nginx配置完全一致,包括大小写。我曾因为一个路径末尾少写斜杠/调试了2小时。
-
代理超时设置:当后端处理时间较长时,需要调整Nginx的代理超时时间:
nginx复制proxy_read_timeout 300s;
proxy_connect_timeout 75s;
- 日志排查技巧:遇到问题时,第一时间查看Nginx访问日志和错误日志:
bash复制tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
- 测试环境验证:建议先在测试环境验证配置,使用docker-compose可以快速搭建测试环境:
yaml复制version: '3'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./dist:/usr/share/nginx/html
backend:
image: your-backend-image
ports:
- "8080:8080"
- 灰度发布策略:为了降低部署风险,可以采用分批次部署:
- 先部署静态文件到新目录
- 测试通过后,修改Nginx配置指向新目录
- 保留旧版本一段时间以便快速回滚