PHP菜鸟博客_共同学习分享PHP技术心得【PHP爱好者】
详解 Vue SPA 路由:# 锚点与 Nginx try_files 解决刷新 404 问题
2025-11-14 菜鸟站长

在 Vue 单页应用(SPA)开发中,路由跳转后刷新页面出现 404 是高频问题。这一现象的核心矛盾,在于前端路由模式与服务器请求逻辑的不匹配 —— 带 # 的哈希模式无需额外配置即可避免刷新报错,而美观的历史模式则需要通过 Nginx 的 try_files 指令兜底。本文将从原理到实践,彻底讲清两者的逻辑与用法。


一、先搞懂:URL 中 # 的特殊作用



Vue 路由默认使用哈希模式(hash mode),其 URL 会带有 # 符号(如 http://xxx.com/#/article/240)。这个看似普通的符号,是解决刷新报错的 “天然屏障”,核心源于其在 URL 中的本质定义:


1. # 是 “片段标识符”,而非服务器请求路径



# 在 URL 中被称为「片段标识符(Fragment Identifier)」,原本用于定位页面内锚点(如 <a href="#section1"> 跳转到页面指定章节)。它有一个关键特性:浏览器不会将 # 及其后面的内容发送给服务器



简单说,当你刷新 http://xxx.com/#/article/240 时,浏览器实际向服务器发送的请求路径只有 http://xxx.com/#/article/240 这部分会被浏览器保留在本地,仅用于前端逻辑处理。


2. 哈希模式刷新不报错的完整流程




  1. 路由跳转时:Vue Router 监听 # 后面的路径变化(如从 #/home 到 #/article/240),通过前端 JS 切换组件,不发起新的服务器请求(这也是 SPA “无刷新跳转” 的核心)。


  2. 页面刷新时:


    • 服务器仅收到根路径 / 的请求,按默认静态文件规则返回 Vue 入口文件 index.html(无需额外配置)。


    • index.html 加载后,Vue 会读取 URL 中 # 后面的路径(/article/240),通过前端路由匹配对应的组件,页面正常显示。





3. 哈希模式的优缺点




二、历史模式:去掉 # 后,为何刷新就 404?



为了获得更简洁的 URL(如 http://xxx.com/article/240),很多开发者会将 Vue 路由切换为历史模式(history mode),只需在路由配置中添加 mode: 'history'








javascript







运行

















const router = new VueRouter({ mode: 'history', // 开启历史模式,去掉 URL 中的 # routes: [...] }) 










但切换后会出现新问题:路由跳转正常,刷新页面直接 404。这背后的逻辑与哈希模式完全不同:


1. 历史模式的核心矛盾



历史模式去掉了 #,URL 与传统多页应用的路径格式一致。此时刷新页面时,浏览器会将整个 URL 路径(如 /article/240)作为请求路径发送给服务器。



而服务器的默认逻辑是:根据请求路径查找对应的文件或目录。由于 Vue 是单页应用,服务器根目录下根本没有 article/240 这个文件或文件夹,因此会返回 404 错误。


2. 对比:两种模式的刷新请求差异




























路由模式

示例 URL

刷新时服务器收到的请求路径

服务器处理结果

哈希模式

http://xxx.com/#/article/240

/(仅根路径)

返回 index.html,页面正常

历史模式

http://xxx.com/article/240

/article/240(完整路径)

找不到对应文件,返回 404




三、Nginx try_files:解决历史模式刷新 404 的关键



要让历史模式既保留美观 URL,又能正常刷新,核心是让服务器 “找不到对应文件时,兜底返回 Vue 入口 index.html”。而 Nginx 的 try_files 指令,正是实现这一逻辑的核心工具。


1. try_files 指令的核心作用



try_files 是 Nginx 的内置指令,作用是按顺序检查请求路径对应的文件 / 目录是否存在,找到第一个存在的资源就返回;若所有路径都不存在,则执行最后一个兜底选项



其语法格式为:








nginx






















try_files $uri $uri/ /index.html; 










逐段拆解每个参数的含义:


(1)第一个参数:$uri —— 优先匹配真实文件



$uri 是 Nginx 内置变量,代表当前请求的路径(不含查询参数)。例如:




(2)第二个参数:$uri/ —— 再匹配真实目录



$uri/ 表示在 $uri 后添加 /,即检查是否存在对应的目录。例如:




(3)第三个参数:/index.html —— 兜底返回 Vue 入口



当前面的文件、目录都找不到时,Nginx 会直接返回根目录下的 index.html。此时:




2. 历史模式的完整 Nginx 配置示例



结合 try_files,历史模式的 Nginx 完整配置如下(可直接复制使用):








nginx






















server { listen 80; # 监听端口 server_name ruoyiblog.wlphp.com; # 你的域名 root /usr/share/nginx/html/ruoyiblog; #  Vue 项目打包后的 dist 目录路径 # 核心配置:解决历史模式刷新 404 location / { try_files $uri $uri/ /index.html; # 按顺序匹配,兜底返回 index.html index index.html index.htm; # 默认首页 } # 可选:配置静态资源缓存(优化性能) location ~* \.(css|js|png|jpg|jpeg|gif|ico)$ { expires 7d; # 静态资源缓存 7 天 add_header Cache-Control "public, max-age=604800"; } } 










配置后执行 nginx -s reload 重启 Nginx,历史模式刷新即可正常显示。


3. 关键注意点




四、总结:两种模式的选择与配置建议




  1. 若追求简单部署,无需美观 URL:直接使用默认的哈希模式,无需配置服务器,刷新永远不会 404。


  2. 若需要无 # 的美观 URL:切换为历史模式,并通过 Nginx 的 try_files 指令配置兜底转发,核心是 try_files $uri $uri/ /index.html;




本质上,# 是通过 “隔离前端路由与服务器请求” 避免 404,而 try_files 是通过 “服务器兜底转发” 解决历史模式的路径匹配问题。两种方案各有优劣,可根据项目需求灵活选择。
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容