路由history模式详解

5 阅读3分钟

本文将从history模式的核心原理出发,拆解404错误的产生原因。

一、history模式到底是什么?

前端路由的本质,是在不刷新整个页面的前提下,实现页面内容的切换——本质是“客户端路由”,由前端框架(Vue、React等)接管路由逻辑,而非依赖后端服务器。

history模式基于浏览器的 History API 实现,主要依赖两个核心方法:

1. pushState():新增历史记录

语法:history.pushState(state, title, url)

作用:向浏览器的历史记录中添加一条新记录,同时修改地址栏的URL,但不会向服务器发送任何HTTP请求

举个例子:在Vue项目中,点击<router-link to="/about">,底层就是调用了pushState(),将URL从 https://xxx.com 改为 https://xxx.com/about,页面内容由Vue路由解析后渲染,全程没有请求服务器。

2. replaceState():替换历史记录

语法:history.replaceState(state, title, url)

作用:和pushState()类似,但它会替换当前的历史记录,而非新增。比如页面跳转时不想留下回退记录(如登录后跳转到首页),就可以用这个方法。

二、history模式为什么会报404?

报404的不是后端接口服务器,而是托管前端静态资源的服务器

我们先分清两个服务器的职责,避免混淆:

1. 两个服务器的区别

  • 「后端接口服务器」:负责提供接口(如 /api/user、/api/list),处理数据查询、业务逻辑,和history模式的404无关。
  • 「前端静态服务器」:负责托管前端打包后的静态资源(npm run build 生成的dist文件夹,里面只有index.html、js、css、图片等),常用的有Nginx、Apache、GitHub Pages、Netlify等,404错误就是这个服务器返回的

2. 404错误的触发逻辑

前端项目打包后,dist文件夹里只有一个入口文件 index.html,没有 about.html、login.html 等物理文件,但history模式的URL会显示 /about/login,这就导致了冲突:

  1. 正常前端跳转:用户从首页点击 /about,前端调用pushState()修改URL,不请求服务器,Vue/React渲染对应页面,无404。
  2. 直接访问/刷新:用户直接在地址栏输入 https://xxx.com/about,或刷新该页面,浏览器会向「前端静态服务器」发送请求,请求路径是 /about。
  3. 服务器校验:静态服务器会查找自己的目录下,是否有 /about 对应的文件或文件夹(比如 about.html),但dist里只有index.html,找不到就返回404。

补充:本地开发时(npm run dev),webpack/vite自带的开发服务器,已经帮我们处理了这个问题——所有找不到的路径,都会自动返回index.html,所以本地开发永远不会报404,只有线上部署时才会出现。

关键区别:history vs hash

很多人会疑惑,为什么hash模式不会有404问题?核心差异在URL的格式和浏览器的处理逻辑:

  • hash模式:URL带#号(如 https://xxx.com/#/about),#后面的内容是“锚点”,浏览器会忽略#后的内容,向服务器请求时,只会发送 https://xxx.com,因此不会触发404。
  • history模式:URL无#号(如 https://xxx.com/about),浏览器会将整个URL作为请求路径,向服务器发送请求,这也是404问题的根源。

三、解决方案

目前博主还未实践过,暂时不描述。

四、总结

前端路由history模式的核心优势是URL简洁、体验更好,而404问题的本质,是「前端静态服务器」找不到URL对应的物理文件,只需通过配置让服务器兜底返回index.html,就能解决。

  • history模式基于浏览器History API,前端跳转不请求服务器,直接修改URL和页面内容;
  • 404错误来自前端静态服务器,和后端接口服务器无关;
  • 所有解决方案的核心,都是让静态服务器将所有路由请求转发到index.html,由前端框架解析路由。