古法编程: 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 内部回退
相关推荐
涛涛ing2 小时前
OpenAI Astra 泄露:零样本生成 3D 网页,前端开发者慌了吗?
前端
ssshooter2 小时前
现在网页都能提供 MCP 了?!
前端·人工智能·程序员
杉氧2 小时前
状态管理变迁史:为什么我们放弃了 Redux 选择 Zustand?
android·前端·react native
cidy_983 小时前
OpenCode 手动配置火山方舟 Agent Plan 教程
前端
鹏多多3 小时前
PC 网站接入微信登录,这 10 个坑我替你踩完了!
前端·javascript·vue.js
律宏阔3 小时前
微信小程序使用 Orval + OpenAPI 自动生成接口:Axios 兼容踩坑记录
前端·微信小程序
律宏阔3 小时前
微信小程序集成 TDesign 完整记录:解决 NPM packages not found
前端·微信小程序
律宏阔3 小时前
微信小程序 ECharts 瘦身实战:分包异步化 + componentPlaceholder 避开主包 2MB 限制
前端·微信小程序
夏天要喝冰可乐3 小时前
从 Idea 到开源插件:我用 Vibe Coding 做了「文章摆渡」
前端·ai编程·vibecoding
小小小小宇3 小时前
pi agent
前端