为解决vue-router mode=history模式,刷新页面404问题而出现的NGINX代理静态资源导致content-type始终为text/html

8,004 阅读3分钟

背景描述:因为研究学习预渲染方面的内容,原先项目前端框架是vue+vue-router,需要将vue-router的模式改为history,但是该模式需要后台配置的配合,因为本人搭建的项目是一个vue的单页应用,所以打包后在服务器上的路径只有一个,当改变url向服务请求静态资源时必定不会成功,当服务器找不到对应的资源时就会返回404;

通过查询网络找到了解决该问题的方法
vue官网的解决方法

如上图所示,官网解决方案为在nginx中设置以上配置,结合自身项目,以下是我自己的配置

因为我是通过在域名后面加一级目录,通过nginx反向代理到指定的项目的,所以在域名后面会加上/prerend来区分,总的效果跟上面官网的解决方法一致
上面配置最重点的一行是

try_files $uri $uri/ /index.html

$uri表示的是与当前路由匹配的内容,举个例子:

当前路由为http://www.juejin.im/prerend,此时$uri=http://www.juejin.im/prerend;

所以上面重点行的意思就是查找当前匹配的路由,没有再找当前路由下面的内容,即$uri/的意义,如果都没有则返回指定文件,我这边包括官网上的设置都是返回首页的index.html文件,这样只要路由刷新找不到对应的资源就会返回首页,并加载首页资源,注意:

/index.html 对应的路径是上面root设置的路径

以上自认为天衣无缝,可以完美解决404的问题了,然鹅,遇到了一个更坑的问题,刷新后虽然没有404,但是页面上也没有任何东西出现
打开chrome检查窗口发现有报错,如下所示:

根据提示是因为css样式表的type类型有问题,于是我打开network界面,看看请求返回的资源,如下所示:

可以看到响应头中Content-Type: text/html,但是根据常识可知,css的content-type应该是text/css,所以这里为什么会这样呢,这个问题困扰我很久,后面发现这个资源的请求中也带有/prerend,那会不会是因为nginx中配置的代理,将原本要返回的css资源替换成了html页面,所以这个地方为text/html了呢,于是又走了很多弯路,查了很多资料还是没有解决;
静下思考一下,因为第一次输入www.xxx.com/prerend时事可以加载出资源的,并且会跳转到www.xxx.com/prenrend/home(因为前端项目中有重定向),但是再次刷新就会出现上面的问题,于是我查看了第一次成功加载时的资源请求是这样的

发现除了content-type变为正常的text/css以外,连请求资源的路径都不一样,之所以加载不出来是因为请求路劲中多了个/prerend,所以可以知道在刷新之后资源的请求地址发生变化了,于是就想到了,是不是在前端打包的时候资源路径引用有问题,打开了页面的elements界面查看资源引用的路径,如下所示:

可以看到所有静态资源都是以相对路径的形式引用的,即当前刷新页面是www.xxx.com/prenred所以资源请求的路劲就以当前/prerend/+资源路劲,所以无法找到相关资源,项目是用vue-cli3.X搭建的,所以这里需要配置vue.config.js,如下所示:

开始的配置是'./',资源路径是相对路径,现在改成了'/',资源路劲就是绝对路径,然后打包上传至服务器,再试运行,就可以了

综上,其实是前端打包配置的疏忽造成了一系列的问题,究其所以还是因为对知识点的模糊不清晰导致的,所以在平时工作学习中应该抓住每一个细节,在解决困难之后才是真正的向前迈进了一步