问题描述
在使用Vue.js
构建的单页应用(SPA
)中,特别是像ruoyi-vue
这样的框架,如果启用了HTML5
历史记录模式进行路由管理,那么用户直接访问子路径或刷新页面时可能会遇到404
错误。这是因为当用户尝试访问一个非根路径时,Nginx
会尝试查找对应的具体文件或目录,而这些资源实际上并不存在于服务器上,导致返回404
错误。
原因分析
该问题的根本原因在于Nginx默认的行为是直接根据请求的URL去寻找静态资源或后端API接口。然而,在单页应用中,所有的前端路由都是通过JavaScript动态处理的,并没有实际对应的物理文件。因此,当用户直接访问或刷新某个子路径时,Nginx无法找到相应的文件,从而返回404错误。
解决方案
为了使Nginx
能够正确处理单页应用的前端路由,我们需要配置Nginx,使其对于所有找不到具体文件或目录的请求都返回index.html文件。这允许Vue Router
接管并根据前端路由配置来显示正确的页面内容。
可以在Nginx配置中的server块内添加以下location指令:
location / {
try_files $uri $uri/ /index.html;
}
这段配置的作用是:
$uri
:首先尝试匹配具体的文件。$uri/
:如果未找到文件,则尝试匹配作为目录。/index.html
:如果前两步均未成功,则提供index.html
文件给客户端,让Vue Router
处理剩下的路由逻辑。
完整的Nginx配置示例
conf {
# 用于 test.com 的 HTTP 服务器块
server {
listen 80;
server_name test.com;
# 将所有 HTTP 请求重定向到 HTTPS
return 301 https://$host$request_uri;
}
# 用于 test.com 的 HTTPS 服务器块
server {
listen 443 ssl;
server_name test.com;
ssl_certificate /etc/nginx/cert/test.com.pem;
ssl_certificate_key /etc/nginx/cert/test.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# 处理前端页面
location / {
root /system/a/b/c/index; # 前端构建输出目录
index index.html index.htm;
try_files $uri $uri/ /index.html; # 尝试访问静态文件,如果不存在则返回 index.html
}
# 处理 API 请求
location /test/ {
proxy_set_header host $host;
proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:9090/; # 将请求代理到本地 9090 端口
# WebSocket 支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
针对服务器面板
如果使用了服务器面板,可以支持一键可视化配置网站应用,但是默认的配置对于SPA
单页应用并不友好,需要手动修改配置,常见的面板有(宝塔
,1Panel
),由于我是用的是1Pane
,这里拿1Panel
举例:
面板原来自动生成的配置:
手动改配置:
注意事项
- 重新加载
Nginx
配置:在修改完配置文件后,请记得执行sudo nginx -s reload
命令以使更改生效。 - 静态资源路径:如果您有额外的静态资源(如图片、CSS、JS等),请确保为它们配置合适的
location
块,并指定正确的路径。 - 缓存控制:对于静态资源,可以考虑设置适当的缓存策略以优化性能,但要考虑到更新频率和缓存清理的问题。