三套路由器,同一个 History

很多开发者以为前端路由很复杂。

但如果你读过 vue-router、react-router、tanstack-router 的源码,你会发现:

底层都是同一套东西:window.history.pushState() + popstate 事件监听。

区别只在上层。

这篇文章从设计哲学层面对比三大路由库的差异,帮你理解它们的核心理念,以及如何选择。

如果你想深入了解每个路由器的源码细节,请阅读本系列的后续文章。


一、底层:惊人相似

三家都在调用同一个浏览器 API:

window.history.pushState(state, '', url)
window.history.replaceState(state, '', url)
window.addEventListener('popstate', handler)

但在 history.state 的存储结构上,设计完全不同:

路由器State 结构设计思路
vue-router{back, current, forward, position, scroll}记录前后关系,方便导航
react-router{usr, key, idx, masked}简洁索引,支持 UI 路由
tanstack-router{__TSR_key, __TSR_index}前缀避免冲突,用于 blocker

二、上层:三种设计哲学

vue-router:渐进式、够用就好

  • History 更新:同步调用
  • 守卫模型:6 层队列(beforeRouteLeave → beforeEach → beforeRouteUpdate → beforeEnter → beforeRouteEnter → beforeResolve → afterEach)
  • 缓存策略:无内置缓存,依赖 Pinia/Vuex
  • 类型安全:基础支持

哲学:Vue 的核心理念是「渐进式」——你可以只用你需要的功能,不需要的可以忽略。6 层守卫看起来复杂,但大多数场景只需要 beforeEach。

react-router:Web 标准优先、Remix 融合

  • History 更新:同步调用
  • 数据模型:loader/action(Request/Response)
  • 守卫模型:middleware + next() 模式
  • 并发控制:AbortController
  • 类型安全:中等推断

哲学:与 Web 标准对齐。loader/action 都接收 Request 对象,返回 Response,让 SSR 变得简单——服务端和客户端用同一套 API。从 Remix 借鉴的设计正在向全栈框架演进。

tanstack-router:性能优先、类型安全极致

  • History 更新:microtask 队列节流 + 猴子补丁拦截原生 API
  • 数据模型:beforeLoad + loader + loaderDeps
  • 缓存策略:LRU Cache + WeakMap + 结构化共享
  • 类型安全:极致推导(ParseRoute 递归类型)

哲学:不惜牺牲代码可读性来换取性能和类型安全。用 Uint16Array 代替对象、用 Trie 代替正则、用猴子补丁拦截原生 API。这种优化在大型应用中效果显著。


三、设计哲学总结

维度vue-routerreact-routertanstack-router
核心理念渐进式、够用就好Web 标准优先、Remix 融合性能优先、类型安全极致
History 更新同步同步microtask 队列节流
API 拦截不拦截不拦截猴子补丁拦截
守卫模型6层队列loader/action + middlewarebeforeLoad + loader
缓存策略shouldRevalidateLRU + 结构化共享
类型安全基础中等极致
代码风格简洁直观优雅抽象性能优化导向

四、选型建议

场景推荐原因
Vue 项目vue-router官方支持,生态最好
React + 全栈框架react-routerRemix/Next.js 集成最好
React + 大型应用 + 类型安全tanstack-router长期收益最高
React + 复杂搜索参数tanstack-routervalidateSearch + 类型推导
需要精细缓存控制tanstack-router结构化共享 + LRU

我的建议

  1. vue-router 没有选择——Vue 项目只能用它,但它足够好用。

  2. react-router 适合大多数 React 项目——Web 标准优先的设计让 SSR 变得简单,与 Remix 的融合也让它成为全栈框架的首选。

  3. tanstack-router 适合长期维护的大型应用——类型安全和缓存优化在项目规模增长后会越来越有价值。但学习成本也最高。


五、造轮子启示录

如果你想自己写一个路由器,核心只需要:

function createRouter(routes) {
  window.addEventListener('popstate', () => {
    const location = parseLocation(window.location)
    const match = matchRoutes(routes, location)
    render(match)
  })

  function navigate(to) {
    const url = buildURL(to)
    history.pushState({}, '', url)
    const match = matchRoutes(routes, parseLocation(url))
    render(match)
  }

  return { navigate }
}

约 20 行代码就能工作。但要成为一个合格的路由库,还需要:

  • 路由匹配算法(静态/动态/通配符)
  • 嵌套路由支持
  • 导航守卫系统
  • 滚动行为恢复
  • View Transitions 支持
  • 并发控制(AbortController)
  • URL 编码处理
  • 搜索参数验证
  • 预加载策略
  • LRU 缓存优化
  • Fog of War 懒发现
  • 懒加载支持
  • SSR 支持
  • 类型安全
  • 开发者工具

这三家在这些方面各有侧重,读它们的源码是理解前端路由最好的方式。


源码版本

  • vue-router: v5.2.0 (packages/router/src/)
  • react-router: v8.x (packages/react-router/lib/router/)
  • tanstack-router: latest (packages/router-core/src/ + packages/history/src/)