问答
问:前端路由和 nginx location 哪个优先级更高?答:当然是 nginx location 优先级更高
因为 nginx location 优先级更高,所以会导致 history 模式的SPA(单页应用)在刷新的时候,会有 404 的问题
场景描述
- 访问
www.abc.com/dashboard,点击logout退出系统,前端路由处理,跳转到www.abc.com/login - 但是登录页面刷新之后,就显示
nginx 404了 - 奇怪的地方就在于,为何退出的时候,重定向到
/login的时候,没有报404, 为何一刷新就 404 了呢? - 前端路由重定向到
/login逻辑:this.$router.push({name: 'login'}); - 贴下前端路由配置
routes: [
{
name: 'home',
path: '/',
component: Home,
meta: { requiresAuth: true },
},
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '*',
component: NotFound,
}
]
-
现有nginx配置
location / { root /var/data/static; }
解决方案
1. 为何点击退出可以正常显示登录页面?
- 因为点击退出,前端路由
this.$router.push({name: 'login'});来实现跳转的,这时候已经有index.html 和相关的js了(也就是说这时候页面跳转的逻辑已经由 Vue-Router 或 React Router 接管了),可以直接使用前端路由跳转到/login路由对应的组件
2. 为何刷新的时候显示: `nginx/404` ?
- 因为刷新的时候,会先向服务器请求
www.abc.com/login> 2. 这时候服务器的nginx配置中没有关于/login路径的配置(即没有location /login {}),因此 nginx 会直接报错nginx/404
3. 如何解决?
按照如下方式配置nginx
location / {
root /var/data/static;
# 意思是说,在nginx 没有找到 /login 路径的时候,不要报错,要把 index.html 返回给客户端
# 这样客户端(浏览器)就能加载到路由相关的js 文件了
# 这时候,路由由前端接管,前端路由会查看路由表里面是否由 /login 的配置,有的话,跳转即可
try_file /index.html;
}
4. 更多解释
1. nginx进行匹配路径的时候,发现没有`/login`的路径,便会转到`/`路径处理。
2. 发现`root`路径下(是静态文件的root目录,不是linux的root目录)没有`login`文件,就会`try_file`规则,返回index.html,
3. 这样浏览器拿到index.html 之后,开始加载其中的前端路由部分
4. 这时候/login就会在前端路由中找到匹配规则。
5. 同理`/404`也可以写在前端路由中了