@reach/router、react-router-dom、react-router-native 和 wouter 都是用于 React 应用的路由解决方案,但针对不同平台和场景。react-router-dom 是面向 Web 的主流路由库,功能全面且活跃维护;react-router-native 专为 React Native 移动应用设计;wouter 是一个极简的 Web 路由替代方案,强调轻量和无依赖;而 @reach/router 已被官方废弃,不应在新项目中使用。这些库共同解决了组件与 URL 路径的映射、导航、参数传递等核心路由需求,但在 API 设计、平台适配和功能深度上存在显著差异。
在现代 React 应用中,路由是不可或缺的核心功能。面对多个可选方案,开发者需要根据项目规模、平台目标、性能要求和维护状态做出合理选择。本文将从真实工程视角出发,深入比较 @reach/router、react-router-dom、react-router-native 和 wouter 四个主流路由库的技术细节、适用场景和关键差异。
首先必须明确:@reach/router 已被官方标记为废弃(deprecated)。根据其 npm 页面 和 GitHub 仓库说明,该库不再接受新功能或重大修复,且其核心作者已将其合并到 react-router v6 中。因此,任何新项目都不应再使用 @reach/router。本文仍将其纳入比较,仅用于帮助维护旧代码的团队理解其定位。
这四个包虽然都解决“路由”问题,但目标平台和抽象层级不同:
react-router-dom:专为 Web 浏览器环境 设计,基于 HTML5 History API,是 React 官方推荐的 Web 路由方案。react-router-native:专为 React Native 移动应用 设计,使用原生导航栈(如 iOS 的 UINavigationController),不适用于 Web。wouter:极简的 Web 路由库,无依赖,API 精简,适合对 bundle size 敏感或追求轻量化的项目。@reach/router(已废弃):曾是轻量级 Web 路由替代方案,强调无障碍(a11y)和简洁 API,现已停止维护。💡 关键区分:
react-router-dom和wouter用于 Web;react-router-native用于 React Native;三者不可混用。
react-router-dom(v6+)使用声明式 <Route> 组件嵌套定义路由,路径匹配基于 嵌套路由(nested routes) 模型。
// react-router-dom
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/users/:id" element={<User />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</BrowserRouter>
);
}
react-router-nativeAPI 与 react-router-dom 高度一致,但底层使用 React Native 的导航组件(需配合 react-navigation 或类似库)。
// react-router-native
import { NativeRouter, Routes, Route } from 'react-router-native';
function App() {
return (
<NativeRouter>
<Routes>
<Route path="/" element={<HomeScreen />} />
<Route path="/profile" element={<ProfileScreen />} />
</Routes>
</NativeRouter>
);
}
wouter采用 Hook 驱动 的极简设计,无需顶层 Provider,直接在组件内使用 useLocation 和 <Route>。
// wouter
import { Router, Route, Link } from 'wouter';
function App() {
return (
<Router>
<Route path="/" component={Home} />
<Route path="/users/:id" component={User} />
</Router>
);
}
// 或使用 Hook
function UserPage() {
const [match] = useRoute("/users/:id");
if (!match) return null;
return <div>User ID: {match.params.id}</div>;
}
@reach/router(已废弃)曾以 自动嵌套 和 无障碍跳转 为特色,路径作为组件 prop 传入。
// @reach/router (deprecated)
import { Router, Link } from '@reach/router';
function App() {
return (
<Router>
<Home path="/" />
<User path="/users/:id" />
</Router>
);
}
react-router-dom:通过 useParams() Hook 获取路径参数。// react-router-dom
import { useParams } from 'react-router-dom';
function User() {
const { id } = useParams();
return <div>User {id}</div>;
}
wouter:通过 useParams() 或 useRoute() 返回的 params 对象获取。// wouter
import { useParams } from 'wouter';
function User() {
const params = useParams();
return <div>User {params.id}</div>;
}
react-router-native:同样使用 useParams(),行为与 Web 版一致。
@reach/router:参数直接作为 props 传入组件。
// @reach/router
function User({ id }) {
return <div>User {id}</div>;
}
react-router-dom:需手动解析 window.location.search 或使用 useSearchParams()(v6.4+)。// react-router-dom
import { useSearchParams } from 'react-router-dom';
function Search() {
const [searchParams] = useSearchParams();
const q = searchParams.get('q');
return <div>Query: {q}</div>;
}
wouter:不内置查询解析,需自行处理或使用第三方工具。
react-router-native:通常不涉及查询字符串(移动端多用深层链接参数)。
所有 Web 方案均提供 <Link> 组件:
// react-router-dom
<Link to="/users/123">Go to User</Link>
// wouter
<Link href="/users/123">Go to User</Link>
// @reach/router
<Link to="/users/123">Go to User</Link>
注意:wouter 使用 href 而非 to,更贴近原生 <a> 标签。
react-router-dom:使用 useNavigate() Hook。const navigate = useNavigate();
navigate('/users/123');
wouter:使用 useLocation() 返回的 setter 函数。const [, setLocation] = useLocation();
setLocation('/users/123');
react-router-native:同样使用 useNavigate(),但底层触发原生导航动画。
@reach/router:使用 navigate() 工具函数。
import { navigate } from '@reach/router';
navigate('/users/123');
Web vs Native:react-router-dom 和 wouter 仅适用于浏览器环境,依赖 window.history;react-router-native 专为 React Native 构建,无法在 Web 使用。试图跨平台混用会导致运行时错误。
React Native 生态:react-router-native 通常需与 react-navigation 等原生导航库协同工作,而 react-router-dom 在 Web 中可独立运行。
无障碍支持:@reach/router 曾以出色的 a11y 支持著称(如自动管理焦点),这一特性已被吸收进 react-router v6 的 <Link> 实现中。
react-router-dom:通过嵌套 <Route> 实现共享布局。<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<Overview />} />
<Route path="settings" element={<Settings />} />
</Route>
wouter:需手动组合组件,无内置嵌套路由支持。
@reach/router:自动基于组件树嵌套匹配路径(已废弃)。
react-router-dom(v6.4+):支持 Loaders 和 Actions,实现数据预加载和表单提交。<Route
path="/users/:id"
loader={async ({ params }) => fetchUser(params.id)}
element={<User />}
/>
react-router-dom:可通过 <Router> 组件注入自定义 history(如内存 history 用于测试)。
wouter:支持自定义 history 适配器,但需额外配置。
react-router-native:使用原生导航历史,不可替换。
react-router-dom。wouter。@reach/router(已废弃)。react-router-native,但需注意其与原生导航库的集成复杂度。@reach/router 迁移:官方推荐升级至 react-router-dom v6,大部分概念(如动态参数、无障碍)已继承。| 特性 | react-router-dom | react-router-native | wouter | @reach/router (废弃) |
|---|---|---|---|---|
| 平台 | Web | React Native | Web | Web |
| Bundle Size | 较大(功能完整) | 中等 | 极小(~2KB) | 小(已停止维护) |
| 嵌套路由 | ✅ 声明式嵌套 | ✅ | ❌ 需手动实现 | ✅ 自动嵌套 |
| 数据加载 | ✅ Loaders/Actions (v6.4+) | ❌ | ❌ | ❌ |
| 无障碍支持 | ✅ 内置 | 依赖原生 | ❌ | ✅(曾是亮点) |
| 自定义 History | ✅ | ❌ | ✅(需适配器) | ✅ |
| 维护状态 | ✅ 活跃 | ✅ 活跃 | ✅ 活跃 | ❌ 已废弃 |
react-router-dom:它是 React 路由的事实标准,功能全面、文档完善、社区支持强大,适合绝大多数应用场景。wouter:如果你的路由逻辑简单(如单页应用、静态站点),且对 bundle size 极度敏感,wouter 是一个优雅的替代方案。react-router-native:尽管生态不如 Web 成熟,但它是官方提供的跨平台路由抽象。@reach/router:已有项目应制定迁移计划至 react-router-dom v6+。路由虽小,却关乎整个应用的架构根基。选择时务必结合平台、功能需求和长期维护性综合判断 —— 别让一时的轻量诱惑,换来未来的迁移成本。
选择 react-router-dom 如果你正在构建一个功能完整的 Web 应用,需要嵌套路由、数据加载(Loaders/Actions)、无障碍支持、SEO 友好性以及强大的社区生态。它是 React Web 路由的事实标准,适合中大型项目和长期维护的产品。
选择 wouter 如果你构建的是轻量级 Web 应用(如静态站点、微前端子应用或演示原型),对 bundle size 极度敏感,且路由需求简单(基本路径匹配和跳转)。它无外部依赖、API 简洁,但缺乏高级功能如嵌套路由和内置数据加载。
不要在新项目中使用 @reach/router,因为它已被官方标记为废弃,不再接收功能更新或重大修复。如果你正在维护一个使用它的旧项目,应计划迁移到 react-router-dom v6 或更高版本,以获得持续的安全更新和新功能支持。
选择 react-router-native 如果你正在开发 React Native 移动应用,并希望使用与 Web 版 react-router 相似的声明式路由 API。它专为原生平台设计,能与 React Native 的导航系统集成,但需注意其功能集相比 Web 版较为有限。
This package simply re-exports everything from react-router to smooth the upgrade path for v6 applications. Once upgraded you can change all of your imports and remove it from your dependencies:
-import { Routes } from "react-router-dom"
+import { Routes } from "react-router"