古法编程: 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 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端