云服务器 99 / 年,新老同享(可以99/年续费),开发者力荐特惠渠道,新客户在享受9折
阿里云推广

详解 Vue SPA 路由:# 锚点与 Nginx try_files 解决刷新 404 问题

  • 内容
  • 评论
  • 相关
在 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 中带有 #,美观度不足;部分场景(如微信分享、SEO 优化)可能受影响。

二、历史模式:去掉 # 后,为何刷新就 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 内置变量,代表当前请求的路径(不含查询参数)。例如:
  • 请求 http://xxx.com/css/app.css$uri 为 /css/app.css,Nginx 会去项目根目录查找该文件,存在则直接返回(保证静态资源正常加载)。
  • 请求 http://xxx.com/article/240$uri 为 /article/240,根目录下无该文件,进入下一个匹配。

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

$uri/ 表示在 $uri 后添加 /,即检查是否存在对应的目录。例如:
  • 请求 http://xxx.com/article/240$uri/ 为 /article/240/,根目录下无该目录,进入最后一个兜底选项。

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

当前面的文件、目录都找不到时,Nginx 会直接返回根目录下的 index.html。此时:
  • 浏览器加载 index.html 后,Vue 会启动并读取 URL 中的路径(/article/240)。
  • Vue Router 匹配对应的路由组件,页面正常显示,完美解决刷新 404 问题。

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. 关键注意点

  • 根目录配置:root 必须指向 Vue 项目打包后的 dist 目录,否则 Nginx 无法找到 index.html 和静态资源。
  • 子目录部署:若项目部署在子目录(如 http://xxx.com/blog/article/240),需在 Vue 路由中设置 base: '/blog/',同时 Nginx 的 location 需改为 location /blog/,确保路径匹配正确。
  • 静态资源兼容:try_files 会优先匹配真实文件(如 cssjsimg),因此静态资源不会被转发,可正常加载。

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

  1. 若追求简单部署,无需美观 URL:直接使用默认的哈希模式,无需配置服务器,刷新永远不会 404。
  2. 若需要无 # 的美观 URL:切换为历史模式,并通过 Nginx 的 try_files 指令配置兜底转发,核心是 try_files $uri $uri/ /index.html;
本质上,# 是通过 “隔离前端路由与服务器请求” 避免 404,而 try_files 是通过 “服务器兜底转发” 解决历史模式的路径匹配问题。两种方案各有优劣,可根据项目需求灵活选择。

本文标签:

版权声明:若无特殊注明,本文皆为《菜鸟站长》原创,转载请保留文章出处。

本文链接:详解 Vue SPA 路由:# 锚点与 Nginx try_files 解决刷新 404 问题 - https://wlphp.com/?post=499

发表评论

电子邮件地址不会被公开。 必填项已用*标注