问题描述
项目打包部署到线上后,发现只有某个页面访问提示404,其他页面可以正常访问。
现象观察和解决办法
该页面的url和该页面的接口都有字符串'/sdk'。尝试修改路由地址为其他值,发现打包部署到线上后,该页面可以正常访问。
原因分析
由于nginx代理文件写了'/sdk'相关代理,所以在history模式下访问带'/sdk'的网页时,会经过'/sdk'的代理,而不是走'/'的代理,后者可以使得页面重定向到index.html,前者导致无法加载页面。nginx部分配置如下:
...省略
upstream aaa.server{
server aaa-server.dev-aaa;
}
server {
listen 80;
location /sdk/ {
proxy_pass http://aaa.server/;
}
location / {
try_files $uri $uri/ /index.html;
}
}
...省略
深层原因分析
hash模式
对于hash模式,访问index/#/a 或 index/#/b 或 其他组件,实际都是请求一个文件即index组件。 #后的这部分 URL 从未被发送到服务器比如nginx,所以它不需要在服务器层面上进行任何特殊处理。
history模式
而对于history模式,访问index/a 或 index/b 或 其他组件,/后的这部分 URL被发送到服务器比如nginx,nginx发现你请求的url比如“index/a”,而nginx里面没有配置 “/a”相关处理,并且webpack打包后文件中并没有a文件(单页面应用),此时访问“index/a就会报404 。由于是单页面应用,打包生成的文件不存在/a或/b这样的html文件,打包只有一个html文件即index.html。
解决办法
添加一个简单的回退路由,把访问结果为404的页面用index.html文件来展示。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面,只是页面内容为index.html,但是url路径仍然为“index/a”,history模式可以监听url变化(hash模式也可以监听url的hash变化)。增加nginx配置:
...省略
server {
...省略
location / {
try_files $uri $uri/ /index.html;
}
}
...省略