古法编程: SPA的路由浅思考

在之前我所有的印象中,往浏览器输入URL,那么就会请求服务器获取资源。毕竟URL又叫统一资源定位器:标识了一个互联网资源的"住址"。

但是 SPA(Single Page Application)单页面应用程序,似乎打破了我这种固有的认知,让我陷入了盲区。我看到它的网络资源地址改变了,但是它并没有向服务器请求?

react-router这家伙就干这样的事情:

  1. 修改了应用程序员的位置URL
  2. 确定在指定的位置渲染哪些React组件

解决盲区痛点

问题1:URL变化了为什么没有请求服务器

URL 变化 ≠ 一定会向服务器发起请求

正常情况下:

js 复制代码
用户点击链接 → 地址栏 URL 变化 → 浏览器向新 URL 发送请求 → 服务器返回页面 → 页面刷新

上面是常见的一个思维定式,因此让很多人觉得URL变化请求服务器是一个不可分割的原子操作 。实际上:改变 URL 是一个动作,向服务器请求是另一个动作

打开浏览器,我们输入reactrouter.com敲回车来到react-router的官网,打开命令行窗口,输入下面的代码

js 复制代码
window.history.pushState({},null,"/home")

结果发现浏览器中的URL已经变化了,但是并没有跳转到home页面

window.history.pushState

pushState 是 HTML5 提供的 History API 中的一个方法,用于在不刷新页面的情况下向浏览器的会话历史栈中添加一个新的历史记录条目。

问题2: URL变化了此时用户手动刷新为什么不404?

经过上面的案例了解到了window.history.pushState的作用。那么好,假如现在用户手动刷新了页面,此时是会向服务器请求资源的。那么为什么刷新之后看起来是正常页面,而不是404?

正常流程应该是这样会报404的:

python 复制代码
1.  用户访问 `https://example.com/`
2.  服务器返回 `index.html`
3.  前端 JS 加载,使用 `pushState` 跳转到 `/user/profile`
4.  地址栏变成 `/user/profile`,页面正常显示 ✅

      **此时用户刷新页面(出问题了):**

5.  用户在 `/user/profile` 页面按 F5 刷新
6.  浏览器向服务器请求 `https://example.com/user/profile`
7.  服务器去找 `/user/profile` 这个路径对应的文件或接口
8.  找不到!返回 404 ❌

        **为什么会 404?**  
        
因为服务器上没有 `/user/profile` 这个真实的文件,它只是前端路由的一个虚拟路径。

但是我们看正常SPA应用程序不会出现404。原因是因为背后的nginx捣的鬼。

nginx配置

try_files 内部回退配置

内部回退的特点:

  • Nginx 内部尝试不同的文件路径
  • 不返回重定向状态码(返回 200)
  • 地址栏 URL 保持不变
  • 用户完全无感知
python 复制代码
# Nginx 配置示例:SPA 所有路由都返回 index.html
location / {
  try_files $uri $uri/ /index.html;
}
参数 说明
$uri 用户请求的原始路径(如 /user/profile
$uri/ 尝试作为目录查找(如 /user/profile/
/index.html 前面都找不到,就返回 index.html

场景:用户刷新 /user/profile

python 复制代码
1. 用户访问 https://example.com/user/profile
   ↓
2. Nginx 尝试找文件:$uri = /user/profile
   → 文件不存在
   ↓
3. Nginx 尝试找目录:$uri/ = /user/profile/
   → 目录不存在
   ↓
4. 最后返回 /index.html(不重定向,直接返回这个文件的内容)
   ↓
5. 浏览器收到 index.html
   ↓
6. 前端 JS 重新加载,读取当前 URL 是 /user/profile
   ↓
7. 前端路由匹配到 /user/profile,渲染对应页面
   ↓
8. 用户看到正确的页面 ✅

小结

以上就是关于react-router在单页面应用程序SPA中对我来说神奇的魔法。总结一下,我缺失的盲区

  1. window.history.pushStateAPI
  2. nginx的try_files 内部回退
相关推荐
小小前端_我自坚强1 小时前
React 核心技术深度笔记
前端·javascript·react.js
Cobyte1 小时前
9.响应式系统演进:effectScope 的作用与实现原理(Vue3.2)
前端·javascript·vue.js
heimeiyingwang1 小时前
【架构实战】微前端架构设计与落地
前端·架构
techdashen2 小时前
Cloudflare HTML 解析器的十年演化史(二)
前端·html
ZC跨境爬虫2 小时前
Apple官网复刻第二阶段day_1:(导航栏模块化重构+工业化可复用UI落地)
前端·javascript·css·ui·重构
天外飞雨道沧桑2 小时前
Node.js在前端开发中扮演的角色
前端·node.js
梅梅绵绵冰2 小时前
若依框架-智慧社区项目
前端·javascript·vue.js
IT_陈寒2 小时前
Vite开发爽是爽,但这个动态导入坑差点让我崩溃
前端·人工智能·后端
Mr_pyx2 小时前
CompletableFuture 使用全攻略:从异步编程到异常处理
linux·前端·python