背景介绍
这几天部署了一个智能BI网站,网站的目录大概是这样:
---/ 主页
---/user
|---/login 登录
|---/register 注册
---/add_chart 新增图表
---/my_chart 我的图表
我的网页逻辑是:
- 如果用户未登录,访问主页、新增图表和我的图表页面都会跳转到登录页面。
- 如果用户已登录,访问主页会直接跳转到新增图表页面。
Bug介绍
假设网页路径为 webUrl,登录成功之后,直接在浏览器输入webUrl/add_chart进入新增图表页面,提示Nginx 404 Not Found;直接在浏览器输入webUrl/,从主页自动跳转到webUrl/add_chart,即新增图表页面后却可以正常访问。
问题分析
查询资料后,发现原因在于我前端使用的是单页应用程序(SPA)架构。这种架构与传统的多页应用程序不同,SPA在初次加载时加载所有必要的资源(HTML、CSS、JavaScript),然后通过AJAX请求动态地更新内容,而无需完全重新加载页面。
简单来说,就是所有的页面路由都在同一个HTML(在我的项目中是index.html)文件上执行。下面是它的一些简单原理:
- 在SPA中,无论你访问哪个路由,浏览器加载的都是同一个index.html文件。
- 初次加载时,SPA会加载所有必要资源,再由前端框架(在我的项目中是React)接管路由管理,通过客户端路由来控制显示不同的页面组件。
- 用户在SPA中导航时,并不会触发浏览器的页面刷新。相反,JS代码会拦截该行为,并动态地更新页面内容,这样用户体验会更流畅。
- 前端框架会监听URL变化,并根据定义的路由规则渲染对应的组件或页面部分。
Bug修复
根据上面的问题分析,初步得出了引起Bug的原因。在Nginx中,默认的是一个页面对应的一个html文件,如主页对应的是index.html,新增图表页面对应的是add_chart.html。所以我们使用网页导航直接访问webUrl/add_chart时,Nginx会寻找add_chart.html,最终导致404错误。
所以解决方案是,无论什么页面请求,都让其导航至index.html。但这样有些粗糙,因为可能有些页面有对应的文件,而有些通过index.html展示。所以正确的做法是,请页面求到来时,先尝试寻找对应的文件,寻找不到在将请求路由至index.html。如访问webUrl/add_chart时,先寻找add_chart.html,如果找不到在路由至index.html。
nginx.conf文件设置如下:
events {
worker_connections 1024;
}
http {
# 省略
server {
# 省略
# ---location块
# 网站主页面
location / {
root /usr/share/nginx/html/project;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# 省略
}
}
其中主要部分是try_files $uri $uri/ /index.html;
。其中try_files告诉Nginx尝试按照顺序查找文件:先尝试请求的URI,其次尝试请求的URI作为目录,最后尝试定位到index.html。