history模式下项目打包后访问某些页面404

414 阅读2分钟

问题描述

项目打包部署到线上后,发现只有某个页面访问提示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;
  }
}

...省略

参考:vue router-history模式