关于路由模式引起的线上页面404

1,938 阅读3分钟

“我正在参加「掘金·启航计划」”

前言

  • 常网IT戳我呀!
  • 常网IT源码上线啦!
  • 本篇录入奔向Linux、Docker专栏,各位看官感兴趣可移步🚶。
  • 最近在新开项目过程中,让同事实习生部署一下到服务器,结果刷新的时候,页面404,连忙问我咋回事?

遇到事情不要慌,越慌则乱。
让我们相信:上天自有安排!

1.jpg

一、发现问题

月明星稀,乌鹊南飞。

正欣赏自己堪称如诗般的代码,感叹到:怎么会人代码写得这么好呢!

同事实习生火冒三级连环QQ就99+,把问题的情况,和觉得自己代码有问题的通通都发来问我。

总结一句,部署到服务器,线上地址刷新页面,404

表扬一下实习生:遇到问题会先自己分析问题,这是程序员的自我修炼。

我不慌不忙,不禁想起那时刚入行的时候,也遇到这个问题,就和同事今天这般慌张。

0099083aa419c344f1c3a73880c4a892 (1).jpg

如今的我黄袍加身,悠闲地在Nginx上加上几行代码,让同事刷新再试一下。

同事狂按F5,竟然访问正常了,大佬,和我说说呗~

下面我们进行分析一下。

二、进行分析

2.1 从路由的视角看问题

同事是在history模式下,刷新的时候,才会产生404的问题。

history模式下,没刷新时,只是通过pushState改变URL,不刷新页面。如果你再跳转路由后再次刷新会得到404的错误,这个错误其实是浏览器会把整个地址当成一个可访问的静态资源路径进行访问,然后服务端并没有这个文件。

如果是Vue的默认路由模式:hash模式就刷新正常。hash模式的工作在前端完成的,不需要后端服务的配合。

没刷新时:
http://192.168/ ==> http://192.168/index.html // 默认访问路径下的index.html文件,normal

http://192.168/home ==> http://192.168/index.html // 访问路径下的index.html文件,normal

http://192.168/info ==> http://192.168/index.html // 所有的路由都是访问路径下的index.html,normal

刷新时:
http://192.168/info ==> http://192.168/info/index.html文件,有问题,服务器上并没有这个资源,404

2.2 Ngxin配置解决方案

🙋使用Vue打包到服务器,上线刷新404的问题?

🙋🏻‍♂️先给出Nginx的解决方案

location / {
    try_files $uri $uri/ @router;	// new add
    index index.html;
}

// new add
location @router {
    rewrite ^.*$ /index.html last;
}

2.3 解读404的产生

当我们访问 http://zhengzemin.cn:3000/itKnowledge/front-end 的时候,服务器会请求你所填写的真实地址。会依次查找文件地址。

itKnowledgefront-end,但是vue项目和普通项目不同,这只是路由,并不是真的文件目录地址。

所有的路由都是依赖SPA单页面的index.html

所以当刷新时,找不到对应,就产生404。

三、解读try_files

在上面的Nginx配置中,我们用到try_files,去查找index.html

try_files字面上的意思:尝试去查找某个静态文件。

try_files $uri $uri/ @router;

$uri:这是nginx的变量,代表用户访问的单文件地址
比如:http://zhengzemin.cn/index.html,那么$uri就是/index.html

$uri/: 这个代表用户访问的文件目录。
比如:http://zhengzemin.cn/index.html, 那么$uri就是 /index.html。

所以,try_files $uri $uri/ @router; 的意思是:http://zhengzemin.cn/dashboard 先去查找单个文件dashboard,如果dashboard不存在,则去查找同名的文件目录/dashboard/,如果再不存在,将进行重定向@router,我们最后一个选项/index.html,发起一个内部"子请求",也就相当于nginx发起一个http请求到http://zhengzemin.cn/index.html

完整的解释就是:try_files 去尝试到网站目录读取用户访问的文件,如果第一个变量存在,就直接返回; 不存在继续读取第二个变量,如果存在,直接返回;不存在直接跳转到第三个参数上。

仔细理解,豁然开朗。

四、解读rewrite

rewrite     [regex]          [replacement]      [flag];
            url正则表达式     替换成真实url       标记(last,break)
            
location @router {
    rewrite ^.*$ /index.html last;
    # 匹配所有	/index.html last;
}

凡是404的路由,都会被重定向到index.html,到index.html之后,交给我们的vue-router路由去加载对应的路由路径,这样子就显示正确了。

关于路由,可以移步开局面试官就让我设计一个路由

知己知彼,百战百胜。

后记

同事投来了羡慕的眼神。

这让我想起大学团委办公室贴的一句标题:未来的你,一定会感谢现在奋斗的你。

遇到问题不要慌,先了解问题所在,排查问题,解决问题并记录问题以免下次遇到。

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

三面:请设计一个虚拟DOM算法吧!

Vue3的响应式到底比Vue2优雅在哪

开局面试官就让我设计一个路由

实战v-model如何绑定多循环表达式(内含原理)

靓仔,说一下keep-alive缓存组件后怎么更新及原理?

面试官问我watch和computed的区别以及选择?

面试官问我new Vue阶段做了什么?

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

VuePress搭建项目组件文档

原文链接

juejin.cn/post/720337…