背景描述
vue项目使用history路由模式进行打包部署,只能直接访问根路径,直接访问子路径会出现404的情况,可以从根路径跳转到子路径,但子路径刷新同样会出现404。
解决方案
Nginx静态服务
修改Nginx配置文件,增加路由未命中时匹配到 /index.html
location / {
root /data/nginx/html;
try_files $uri $uri/ /index.html;
}
## 或者
location /{
root /data/nginx/html;
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
break;
}
}
Node服务
引入一个node中间件,在请求路径匹配不上时指向 /index.html
github地址 github.com/idseventeen…
const Koa = require('koa');
// require 'koa2-connect-history-api-fallback' middleware
const { historyApiFallback } = require('koa2-connect-history-api-fallback');
// create app
const app = new Koa();
// use historyApiFallback
app.use(historyApiFallback());
问题原因
为甚hash模式不会出现404而history模式会出现404?
这里需要熟悉Vue的两种路由模式
hash模式下,URL和路由路径由#号分隔,当#后面的路径发生变化时,会触发浏览器的hashchange事件,通过hashchange事件监听到路由路径的变化,从而导航到不同的路由页面。
但是,hash模式#后面的路径并不会作为URL出现在网络请求中,例如对于输入的www.hello.com/#/profile ,实际上请求的URL是www.hello.com ,所以不管输入的hash路由路径是什么,实际网络请求的都是根路径,会匹配到默认配置的index.html入口文件,而具体的路由匹配由vue-router接管。
而history模式下,URL和路径是连接在一起的,路由的路径包含在请求的URL里面,路由路径作为URL的一部分一起发送,这就会导致服务端路径匹配不上,比如Nginx只配置了根路径匹配index.html,对于/profile就匹配不上。
解决思路
清楚了原因,那么这个问题的解决思路就有了:修改服务端的配置,在路径匹配不上的情况下,将其指向index.html文件,具体的路由匹配由vue-router接管。