近日,随着React生态中路由库的版本迭代与社区讨论升温,一个由来已久的问题再次浮出水面:在构建React应用时,究竟该使用react-router还是react-router-dom?看似简单的二选一,背后却折射出框架设计哲学、包管理策略以及开发者体验的深层博弈。本报记者走访多位前端专家,梳理这场“路由之争”的来龙去脉。

同根同源,各有侧重

React Router作为React官方推荐的路由解决方案,自诞生以来便采用分层架构。其核心包react-router提供了路由匹配、导航、路径解析等底层逻辑,但本身并不与任何平台绑定。而为了适配Web端特有的DOM操作(如浏览器历史记录、URL变化监听、链接点击),社区又推出了react-router-dom,它封装了BrowserRouterHashRouterLinkNavLink等组件,本质上是对核心包的增强。

“很多新手直接安装react-router-dom,却不知道react-router也会被作为依赖自动安装。”前美团前端架构师李然向记者解释道,“react-router-dom只是重新导出了react-router的所有API,并额外添加了与DOM相关的功能。这意味着,如果你在Web项目里单独安装react-router,将无法使用<Link><BrowserRouter>——这些组件属于上层封装。”

混淆之源:从v4到v6的演变

早在React Router v4时代,官方文档就明确建议Web开发者安装react-router-dom。但许多开发者发现,自己在代码中引用的RouteSwitch等核心组件既可以从react-router导入,也可以从react-router-dom导入——因为后者对前者做了再导出。这种“重复导出”设计直接导致了两大问题:一是部分初学者误认为两者可以互换,二是项目体积可能因同时安装两个包而膨胀。

进入v6时代,React Router团队对包结构进行了优化:react-router-dom现在完全依赖react-router,但不再盲目再导出所有API,而是明确区分了平台相关与通用组件。例如,useParamsuseNavigate等钩子依然从react-router导入,而useHrefuseLinkClickHandler则仅存在于react-router-dom中。然而,这种调整并未彻底消除混淆——由于react-router仍然作为隐式依赖存在,开发者若无意中直接引用它,可能导致版本不一致的运行时错误。

平台化需求:不止于Web

争议的另一焦点在于react-router-native的存在。该包专为React Native设计,同样基于react-router核心,但摒弃了DOM API,改用Native的BackHandlerLinking。这进一步凸显了分层设计的价值:一次编写路由逻辑,跨平台共享核心代码。

“对于只做Web项目的团队,直接选react-router-dom是最稳妥的方案。”阿里云前端技术专家王思远指出,“但如果公司同时维护Web端和移动端应用,建议统一安装react-router作为基础依赖,再按需添加react-router-domreact-router-native。这样能避免核心逻辑重复打包,也方便切换运行时。”

社区呼声:简化还是解耦?

在GitHub Issue和Stack Overflow上,关于这两者的讨论已持续数年。有开发者直言:“我根本不关心底层实现,只想一个npm install就能干活。”而另一派则认为,React Router团队坚持平台无关理念是正确的,因为它允许社区在此基础上开发其他平台适配器(如React VR、React Three Fiber等)。

最新数据显示,截至2025年4月,npm上react-router-dom的周下载量超过1400万次,是react-router的3倍以上。但值得注意的是,大量下载来自同一项目的自动依赖——默认情况下,react-router-dom会自动安装react-router。若统计实际被显式声明的依赖,react-router-dom约占Web项目的95%。

选型指南:三条黄金法则

基于多位一线开发者的经验,记者整理了以下决策建议:

  1. 纯Web项目:直接安装react-router-dom,无需显式添加react-router。代码中从react-router-dom按需导入组件和钩子。
  2. 跨平台项目:安装react-router作为核心,并分别添加react-router-dom(Web)和react-router-native(Native)。注意统一版本号,防止核心包冲突。
  3. 库/组件层:如果开发通用React组件库(不绑定平台),应仅依赖react-router,让使用者自行选择上层适配器。

结语

react-routerreact-router-dom之争,本质是“最小依赖”与“开箱即用”两种设计哲学的较量。对于绝大多数开发者而言,答案已经清晰:做Web,选react-router-dom;做生态,坚守react-router 与其纠结于二选一,不如理解其设计初衷——React Router团队用包拆分为我们铺好了路,而选择权,始终在懂业务的开发者手中。

(本报记者 陈立 报道)