react-router-dom 是 React 生态中最标准的路由解决方案,提供完整的浏览器路由功能。react-router 是其核心依赖包,通常不单独用于 Web 开发。@reach/router 曾是竞争者,但已废弃并合并入 React Router v6。wouter 是一个极轻量的替代方案,适合对包体积敏感或需要简单路由的场景。本文将帮助开发者根据项目规模和维护需求做出正确选择。
在 React 生态中,路由管理是构建单页应用(SPA)的核心环节。react-router-dom 长期占据主导地位,但 wouter 提供了轻量级替代方案,而 @reach/router 已成为历史。作为架构师,我们需要清楚每个包的定位、API 风格以及维护状态,以便为团队选择最合适的工具。
选择库的第一步是确认它是否活着。维护状态直接影响项目的长期安全性。
@reach/router 已正式废弃。
// @reach/router: legacy API (已废弃)
import { Router, Route } from "@reach/router";
function App() {
return (
<Router>
<Home path="/" />
<User path="/user/:id" />
</Router>
);
}
react-router 是核心库。
Link)。// react-router: 核心逻辑 (通常不直接使用)
import { Router } from "react-router";
import { createBrowserHistory } from "history";
// 需要手动创建 history 对象,适合非 DOM 环境
const history = createBrowserHistory();
react-router-dom 是 Web 标准实现。
react-router 构建,增加了浏览器特定功能。// react-router-dom: 标准 Web 实现
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user/:id" element={<User />} />
</Routes>
</BrowserRouter>
);
}
wouter 是轻量级活跃项目。
// wouter: 轻量级实现
import { Router, Route } from "wouter";
function App() {
return (
<Router>
<Route path="/" component={Home} />
<Route path="/user/:id" component={User} />
</Router>
);
}
路由库的 API 设计决定了代码的编写方式。现代 React 开发更倾向于 Hooks,但组件式声明依然流行。
react-router-dom 支持组件与 Hooks 混合。
<Routes> 组件配合 useNavigate 等 Hooks。// react-router-dom: Hooks 导航
import { useNavigate } from "react-router-dom";
function LoginButton() {
const navigate = useNavigate();
return <button onClick={() => navigate("/dashboard")}>登录</button>;
}
wouter 纯粹基于 Hooks。
useRoute 和 useLocation。// wouter: 纯 Hooks 匹配
import { useRoute } from "wouter";
function UserPage() {
const [matches, params] = useRoute("/user/:id");
return matches ? <div>ID: {params.id}</div> : null;
}
@reach/router 仅支持组件式。
// @reach/router: 旧式 Props 导航
import { Link } from "@reach/router";
// 只能使用 <Link> 组件,缺乏编程式导航的灵活性
<Link to="/dashboard">前往仪表板</Link>
react-router (核心) 提供底层 Hooks。
useRouter 等底层能力。// react-router: 底层 Hook
import { useRouter } from "react-router";
// 用于获取内部 router 对象,普通业务很少用到
const { navigator } = useRouter();
现代路由库不仅仅是跳转,还涉及数据获取。这是区分重型与轻型方案的关键点。
react-router-dom 支持数据路由(v6.4+)。
loader 和 action 机制,类似 Remix。// react-router-dom: 数据加载
import { useLoaderData } from "react-router-dom";
export async function loader() {
return fetch("/api/user");
}
function UserPage() {
const user = useLoaderData();
return <div>{user.name}</div>;
}
wouter 不包含数据加载逻辑。
// wouter: 手动数据加载
import { useRoute } from "wouter";
import useSWR from "swr";
function UserPage() {
const [matches, params] = useRoute("/user/:id");
const { data } = useSWR(matches ? `/api/user/${params.id}` : null);
return data ? <div>{data.name}</div> : null;
}
@reach/router 无内置数据加载。
// @reach/router: 手动 useEffect 加载
import { useEffect, useState } from "react";
function UserPage({ id }) {
const [user, setUser] = useState(null);
useEffect(() => { fetch(`/api/user/${id}`).then(setUser); }, [id]);
return user ? <div>{user.name}</div> : null;
}
react-router (核心) 无 DOM 数据加载。
// react-router: 无内置 fetch
// 开发者需自行结合上下文或外部库实现
复杂应用通常需要嵌套布局(例如侧边栏 + 内容区)。不同库的处理方式差异巨大。
react-router-dom 使用 <Outlet> 组件。
// react-router-dom: 嵌套布局
import { Outlet } from "react-router-dom";
function DashboardLayout() {
return (
<div>
<Sidebar />
<Outlet /> {/* 子路由渲染在这里 */}
</div>
);
}
wouter 通过组件组合实现。
<Outlet>,依靠子组件渲染逻辑。// wouter: 手动组合布局
function DashboardLayout({ children }) {
return (
<div>
<Sidebar />
{children}
</div>
);
}
// 使用时需手动匹配子路由
@reach/router 使用 props.children。
// @reach/router: 隐式 children
function Dashboard({ children }) {
return <div>{children}</div>;
}
react-router (核心) 提供 <Outlet> 逻辑。
react-router-dom 复用了此能力。// react-router: 底层 Outlet
// 内部实现逻辑,通常通过 react-router-dom 暴露
| 特性 | react-router-dom | wouter | @reach/router | react-router |
|---|---|---|---|---|
| 维护状态 | ✅ 活跃维护 | ✅ 活跃维护 | ❌ 已废弃 | ✅ 活跃维护 |
| 包体积 | 较大 (功能全) | 极小 (~1.5KB) | 中等 | 小 (核心) |
| API 风格 | 组件 + Hooks | 纯 Hooks | 仅组件 | 底层 Hooks |
| 数据加载 | 内置 Loader/Action | 需配合外部库 | 无 | 无 |
| 嵌套路由 | <Outlet> 支持 | 手动组合 | children 传递 | 底层支持 |
| 适用场景 | 企业级/复杂应用 | 轻量/微前端 | 不应使用 | 库开发/通用逻辑 |
react-router-dom 是大多数团队的标准选择 🏆。
它提供了最完整的功能集,包括数据加载、嵌套路由和完善的类型定义。虽然体积稍大,但对于商业项目来说,稳定性和生态支持更重要。如果你正在构建一个需要长期维护的后台系统或复杂 SPA,不要犹豫,选它。
wouter 是特定场景下的利器 🔪。
当你需要极致轻量,或者在微前端架构中集成一个小型子应用时,它的简单性就是优势。没有复杂的配置,引入即可用。但要注意,复杂的数据流需要你自己设计。
@reach/router 和 react-router (单独) 应避免 🚫。
前者已死,后者太底层。除非你是库作者,否则不要在生产环境中直接依赖 react-router 核心包,也不要在新项目中触碰 @reach/router。
总结:路由选型本质是在“功能完整性”与“轻量级”之间做权衡。对于 90% 的 Web 项目,react-router-dom 是最稳妥的决定;对于剩余 10% 的极端场景,wouter 提供了优雅的退路。
不要在新项目中使用此包。官方已明确标记为废弃(Deprecated),其功能已完全合并到 React Router v6 中。继续使用该包会导致无法获得安全更新和新特性支持,迁移成本也会随时间增加。请直接评估 react-router-dom 作为替代方案。
通常不需要单独安装此包,除非你在编写与平台无关的通用路由逻辑。它是 react-router-dom 和 react-router-native 的核心依赖,提供了底层的路由状态管理。对于大多数 Web 开发者,直接安装 react-router-dom 即可,它会自动包含核心功能。
这是构建标准 React Web 应用的首选方案。如果你需要完整的功能集,包括嵌套路由、数据加载(v6.4+)、搜索参数处理和强大的社区生态,请选择它。适合企业级应用、复杂后台管理系统以及需要长期维护的大型项目。
如果你的项目对包体积非常敏感,或者只需要基本的路由匹配功能,wouter 是最佳选择。它基于 Hooks 设计,API 极其简单,没有复杂的上下文开销。适合微前端子应用、小型工具类页面或作为大型应用中的轻量级路由模块。
Next Generation Routing for React
You can also find the docs in the website directory.
MIT License Copyright (c) 2018-present, Ryan Florence