Wouter
极简的 React 路由库,仅 ~2KB gzipped,提供最核心的路由功能。
Wouter 是极简主义 React 路由库,包体积仅约 2KB,核心 API 只有三个 hooks 和几个组件,不内置数据加载和路由守卫,适合小型 SPA、嵌入式 widget 和包体积极度敏感场景。
Wouter
极简的 React 路由库,仅 ~2KB gzipped,提供最核心的路由功能。
技术简介说明
Wouter 是一个极简主义的 React 路由库,由 Alexey Taktarov(molefrog)创建。它的核心设计目标是"做最少的事"——仅提供路由匹配和导航的基本能力,包体积压缩后仅约 2KB(gzipped)。在 React Router 动辄 45KB+ 的今天,Wouter 为那些不需要复杂路由功能的应用提供了一个极其轻量的替代方案。
Wouter 的设计理念是"hooks 优先"——核心 API 只有三个 hooks:useRoute、useLocation 和 useRouter,加上 <Router>、<Route>、<Link> 和 <Redirect> 几个组件。它不内置数据加载、路由守卫、嵌套路由等高级功能,而是将这些留给开发者按需自行实现。这种"零魔法"的设计让开发者完全掌控路由逻辑,同时避免了不必要的抽象层。
Wouter 支持浏览器(基于 location 和 history API)、哈希路由和内存路由三种模式,底层使用正则表达式进行路径匹配。虽然功能精简,但它的路由匹配能力足以覆盖大部分基础路由场景,包括动态参数、通配符、可选参数等。
基本信息
- 官网:https://github.com/molefrog/wouter
- GitHub:https://github.com/molefrog/wouter
- License:ISC(类似 MIT)
- 最新版本:v3.7.0(2025年)
- 主要维护者/公司:Alexey Taktarov(molefrog)及社区贡献者
快速上手
安装
# npm
npm install wouter
# pnpm
pnpm add wouter
# yarn
yarn add wouter基础配置
Wouter 无需特殊配置,安装后即可使用。默认使用浏览器 History API。
import { Route, Link, Switch } from 'wouter'
function App() {
return (
<div>
<nav>
<Link href="/">首页</Link>
<Link href="/about">关于</Link>
</nav>
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/user/:name" component={User} />
<Route component={NotFound} />
</Switch>
</div>
)
}最小示例
import { render } from 'react-dom'
import { Link, Route, Switch } from 'wouter'
function Home() {
return <h1>首页</h1>
}
function About() {
return <h1>关于</h1>
}
function User({ params }: { params: { name: string } }) {
return <h1>你好,{params.name}!</h1>
}
function App() {
return (
<div>
<nav>
<Link href="/"><a>首页</a></Link>
<Link href="/about"><a>关于</a></Link>
<Link href="/john"><a>John</a></Link>
</nav>
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/:name" component={User} />
</Switch>
</div>
)
}
render(<App />, document.getElementById('root'))使用 Hooks API:
import { useRoute, useLocation } from 'wouter'
function App() {
const [location, setLocation] = useLocation()
const [match, params] = useRoute('/user/:id')
return (
<div>
<p>当前路径:{location}</p>
{match ? (
<p>用户 ID:{params?.id}</p>
) : (
<p>未匹配</p>
)}
<button onClick={() => setLocation('/user/42')}>
导航到用户 42
</button>
</div>
)
}核心概念与架构
极简 API 设计
Wouter 的核心 API 只有:
<Route>:路由匹配组件,支持path、component、children<Switch>:互斥路由匹配(只渲染第一个匹配的 Route)<Link>:导航链接组件<Redirect>:重定向组件useRoute(path):匹配当前路径是否匹配指定模式useLocation():获取/设置当前位置useRouter():访问路由器实例
路径匹配
Wouter 使用正则表达式进行路径匹配,支持:
- 动态参数:
/user/:id - 通配符:
/files/* - 可选参数:
/file/:name? - 自定义匹配器:传入函数代替字符串
三种 History 模式
- 浏览器模式(默认):基于
window.history和popstate事件 - 哈希模式:基于
window.location.hash,通过hashRouter启用 - 内存模式:基于内存中的 location 状态,适用于测试和 SSR
import { Router } from 'wouter'
import { hashLocation, memoryLocation } from 'wouter/memory'
// 哈希路由
<Router hook={hashLocation}>
<App />
</Router>
// 内存路由(测试用)
const [hook] = memoryLocation({ initial: '/home' })
<Router hook={hook}>
<App />
</Router>无状态设计
Wouter 本身不维护路由表状态,它是一个"无路由表"的路由器。每个 <Route> 独立匹配当前 URL,<Switch> 提供互斥匹配。没有嵌套路由的概念——需要嵌套布局时,直接在组件内组合即可。
核心特性
- 极小包体积:~2KB gzipped,远小于 React Router
- Hooks API:
useRoute、useLocation、useRouter三个核心 hooks - 声明式组件:
<Route>、<Switch>、<Link>、<Redirect> - 动态路由参数:
:id、*、:name?等模式 - 自定义匹配器:支持传入函数进行自定义路径匹配
- 多种 History 模式:浏览器、哈希、内存三种模式
- 零依赖:不依赖
history、path-to-regexp等外部库 - TypeScript 支持:完整的类型定义
- React 18 兼容:支持 Concurrent Mode 和 Strict Mode
- SSR 友好:内存路由模式支持服务端渲染
- 嵌套布局:通过组件组合实现,无框架级限制
生态图
关键依赖
- React ≥ 16.8:核心框架依赖(需要 Hooks 支持)
- 无其他运行时依赖
相关插件与扩展
- wouter-params:增强型路由参数处理
- wouter-transition:路由切换动画(实验性)
- 社区自定义 matcher 和 middleware
社区生态
- 相比 React Router,Wouter 的社区生态较小
- 主要作为轻量替代方案在特定场景使用
- 常见于微前端、嵌入式 widget、小型 SPA
- GitHub 上有大量基于 Wouter 的示例和模板
与其他轻量路由对比
- Wouter vs Reach Router:Reach 已归档,Wouter 仍在维护
- Wouter vs React Router:功能差异巨大,定位不同
适用场景
- 小型 SPA:页面少于 10 个的简单单页应用
- 嵌入式组件/Widget:需要在已有应用中嵌入路由功能
- 微前端子应用:子应用需要独立路由但要求包体积最小
- 原型/快速开发:快速搭建带路由的原型,无需复杂配置
- React 学习项目:学习 React 路由概念的最简方案
- 包体积敏感的场景:对加载性能有严格要求的项目
- 测试环境:内存路由模式适合单元测试
开发与工程化
开发流程
# 在现有 React 项目中添加
npm install wouter
# 无需额外配置,直接使用
npm run dev项目结构建议
src/
├── components/
│ ├── Layout.tsx # 布局组件
│ └── Nav.tsx # 导航组件
├── pages/
│ ├── Home.tsx # 首页
│ ├── About.tsx # 关于页
│ └── UserDetail.tsx # 用户详情
├── routes.tsx # 路由配置
├── matchers.ts # 自定义匹配器(可选)
└── App.tsx
自定义匹配器
import { Route } from 'wouter'
import type { Matcher } from 'wouter'
// 自定义匹配器:忽略大小写
const caseInsensitive = (pattern: string): Matcher => {
return (path: string) => {
if (path.toLowerCase() === pattern.toLowerCase()) {
return {}
}
return null
}
}
// 使用
<Route matcher={caseInsensitive} path="/About" component={About} />路由鉴权
// Wouter 不内置鉴权,需要自行实现
function ProtectedRoute({ path, children }: { path: string; children: React.ReactNode }) {
const [match] = useRoute(path)
const isAuthenticated = useAuth()
if (!match) return null
if (!isAuthenticated) return <Redirect to="/login" />
return <>{children}</>
}
// 使用
<ProtectedRoute path="/dashboard">
<Dashboard />
</ProtectedRoute>测试
import { render, screen } from '@testing-library/react'
import { Router } from 'wouter'
import { memoryLocation } from 'wouter/memory'
test('renders home page', () => {
const [hook] = memoryLocation({ initial: '/' })
render(
<Router hook={hook}>
<Route path="/" component={Home} />
</Router>
)
expect(screen.getByText('首页')).toBeInTheDocument()
})性能与安全
性能特点
- 极小包体积:~2KB 对首屏加载影响可忽略
- 无路由表构建:不需要构建路由树,每个 Route 独立匹配
- 高效正则匹配:路径匹配使用编译后的正则表达式
- 最小重渲染:只有匹配的路由组件渲染
优化建议
- 对于大量路由(50+),考虑将
useRoute的结果缓存 - 使用
React.memo包裹路由组件减少不必要的重渲染 <Switch>组件确保只有一个路由渲染- 将不常用的路由组件使用
React.lazy懒加载
安全注意事项
- XSS 防护:路由参数可能包含用户输入,渲染时注意转义
- 路由鉴权:需要自行实现,Wouter 不提供内置守卫
- 开放重定向:
<Redirect>的to属性需要验证 - 敏感路由:不要在 URL 中暴露敏感信息
已知性能瓶颈
- 大量
<Route>组件(100+)时的匹配开销 - 每次 location 变化时所有
useRoutehooks 都会执行 <Switch>内大量路由的线性匹配- 缺少预加载和代码分割的内置支持
技术对比
| 特性 | Wouter | React Router v7 | TanStack Router | Reach Router |
|---|---|---|---|---|
| 包体积 | ~2KB | ~45KB | ~30KB | ~8KB |
| 路由表 | 无 | 有 | 有 | 有 |
| 嵌套路由 | ❌ 需组件组合 | ✅ 原生支持 | ✅ 原生支持 | ✅ 原生支持 |
| 数据加载 | ❌ 无 | ✅ Loader/Action | ✅ Loader | ❌ 无 |
| 路由守卫 | ❌ 需自行实现 | ⚠️ 部分 | ✅ beforeLoad | ❌ 无 |
| 代码分割 | ❌ 需手动 | ✅ lazy() | ✅ 自动 | ✅ 支持 |
| 类型安全 | ⚠️ 基础 | ⚠️ 部分 | ✅ 完整 | ❌ 弱 |
| SSR 支持 | ⚠️ 内存模式 | ✅ 完整 | ✅ 支持 | ⚠️ 有限 |
| 学习曲线 | 极低 | 中等 | 较陡 | 低 |
| 社区规模 | 小型 | 极大 | 增长中 | 已停止 |
| 适用项目大小 | 小型 | 中大型 | 中大型 | 小型 |
| 维护状态 | 活跃(小型) | 活跃 | 活跃 | 已归档 |
最佳实践
路由组织
// ✅ 推荐:将路由配置集中在一个文件
// routes.tsx
import { Route, Switch } from 'wouter'
import Home from './pages/Home'
import About from './pages/About'
import UserDetail from './pages/UserDetail'
import NotFound from './pages/NotFound'
export function AppRoutes() {
return (
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/user/:id" component={UserDetail} />
<Route component={NotFound} />
</Switch>
)
}代码分割
// ✅ 推荐:手动实现路由级代码分割
import { lazy, Suspense } from 'react'
import { Route, Switch } from 'wouter'
const Home = lazy(() => import('./pages/Home'))
const About = lazy(() => import('./pages/About'))
const Dashboard = lazy(() => import('./pages/Dashboard'))
function AppRoutes() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/dashboard" component={Dashboard} />
</Switch>
</Suspense>
)
}全局导航钩子
// ✅ 推荐:封装导航逻辑
import { useLocation } from 'wouter'
function useNavigation() {
const [, setLocation] = useLocation()
return {
navigate: (to: string) => setLocation(to),
goBack: () => window.history.back(),
goForward: () => window.history.forward(),
}
}
// 使用
function MyComponent() {
const { navigate } = useNavigation()
return <button onClick={() => navigate('/about')}>关于</button>
}常见陷阱
- ❌ 不要在 Wouter 中期望嵌套路由功能——需要自行通过组件组合实现
- ❌ 不要假设 Wouter 提供数据加载——需要配合 useEffect 或其他库
- ❌ 不要将 Wouter 用于需要复杂路由鉴权的大型应用
- ❌ 不要忘记
<Link>需要包裹<a>标签(Wouter 的<Link>不直接渲染<a>)
技术局限与边界
已知限制
- 无嵌套路由:不支持框架级别的嵌套路由
- 无数据加载:没有 loader/action 等数据获取机制
- 无路由守卫:鉴权、重定向等需要自行实现
- 无代码分割:不支持自动路由级代码分割
- 无预加载:没有 Link 预加载功能
- 社区生态小:第三方插件和教程资源有限
- 功能有限:不适合复杂的企业级路由需求
不适用场景
- 大型企业级应用(需要完整路由功能)
- 需要 SSR/SSG 的复杂项目
- 需要路由鉴权和权限控制的应用
- 需要类型安全路由的项目
- 需要复杂数据加载和表单处理的应用
- 需要嵌套路由和布局路由的项目
迁移注意事项
- Wouter → React Router:需要重构路由配置,添加数据加载和守卫逻辑
- React Router → Wouter:删除高级路由功能,简化为组件组合模式
- 建议:如果项目需求增长超出 Wouter 能力,应尽早迁移到 React Router 或 TanStack Router
学习资源
- GitHub 仓库(含文档):https://github.com/molefrog/wouter
- 示例:https://github.com/molefrog/wouter/tree/master/packages/wouter
- 教程:
- Wouter README - 最完整的参考
- React 轻量路由方案对比
- 社区资源:
- GitHub Issues - 讨论和反馈
- Stack Overflow #wouter
- 视频:
2026 年现状
最新版本
Wouter v3.7.x 是当前稳定版本(2025年),保持低频更新。
发展趋势
- 维护模式:更新频率较低,以 bug 修复为主
- 稳定 API:API 已趋于稳定,很少有大变更
- ** niche 定位**:明确定位为轻量替代方案,不追求功能全面
- React 19 兼容:持续跟进 React 新版本的兼容性
社区活跃度
- GitHub Stars:~7k
- npm 周下载量:~50万+
- 贡献者:30+
- 更新频率:每季度 1-2 次更新
未来路线图
- React 新版本兼容维护
- 可能的 TypeScript 类型改进
- 不会有大的功能扩展(保持极简定位)
- 社区驱动的 bug 修复和小型改进