一文搞懂Vue history模式打包刷新页面404问题

6,435 阅读2分钟

背景描述

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接管。