问题出现的环境背景:
vue项目打包生成dist文件夹,将dist放到本机的nginx下运行,打开页面,正常点击菜单时,可以打开页面,除了主页,其他路由页面使用浏览器刷新或者复制url地址打开时,会出现页面404的情况。nginx的配置如下:
server {
# ...其他部分省略...
listen 8081;
server_name localhost;
location / {
root xxx/dist; # xxx 表示vue项目路径
index index.html index.htm;
}
# ...其他部分省略...
}
问题定位
由于vue项目中router使用的mode为history:
分析:
-
vue-router
默认是hash
模式,使用url
的hash
来模拟一个完整的url
,当url
改变的时候页面不会重新加载,hash
模式路由中会携带#
history
模式的路由,url
中不携带#
。history
模式的路由需要后台配置的支持,否则只有在项目主页(也就是根路由下,eg:http://localhost:8081/
)时能正常访问,在其他路由页面(eg:http://localhost:8081/filter-list
)刷新或者直接复制地址打开时就会出现404的情况
因为在history模式下,只是动态的通过js来操作window.history来改变浏览器的地址,并没有发起http请求,但是当直接在浏览器中输入地址时,就一定要对服务器发起http请求,但是这个目标不存在服务器上,所以返回404
但是在开发环境使用history模式又不会出现问题,是因为开发时用的是node为服务器,dev环境中已经配置好了
那么在nginx启动的情况下如何去解决404的问题呢?(参考vue-router官方给出的解决办法)
- 在nginx的配置文件(nginx.conf文件)中添加
try_files $uri $uri/ /index.html
- 重启打开页面刷新检查是否有效,如果前端路由部分代码没有问题,一般情况下,就能正常刷新了
- 如果此时率先你页面显示空白,不是显示404了,此时需要去检查一下代码是否出现了问题
当我修改了路由中自定义的prefixPath之后,就能正常刷新页面了----------------------------------------------------------------------------------------
简单解释try_files
指令:
(可参考文章对该指令的解释)
-
try_files $uri $uri/ /index.html
:它的作用是按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向走到最后一个参数。 - 需要注意的是,只有最后一个参数能引起一个内部重定向,之前的参数只能设置内部的uri的指向。最后一个参数是回退uri且必须存在,否则会引起内部500的错误
- 举例:假如root是这样定义的
root xxx/dist; # xxx 表示vue项目路径
,浏览器中的地址为http://localhost:8084/data-list
那么就是寻找xxx/dist/$uri
,其中$uri
就是URL中的路径,即/data-list。所以最终访问的就是xxx/dist/data-list,访问不到data-list这个文件就继续查找data-list/这个文件夹,都不存在,就返回最后一个参数index.html,也就是xxx/dist/index.html。