创见博客
Next.js的路由原理
七崽爱吃小饼干2026/01/13阅读 0专栏 React

Next.js 路由 与 BrowserRouter/HashRouter 的关系 & 底层原理深度解析

核心结论

Next.js 的路由系统,完全不是基于 React Router 的 BrowserRouter / HashRouter 实现的,二者没有任何继承/依赖关系,是两套完全独立、毫无关联的路由体系。

补充关键认知:

  1. Next.js 是自带路由系统的全栈框架,它的路由能力是框架内置原生实现的,不需要安装 react-router-dom,也不会依赖其中任何一个路由容器;
  2. Next.js 的路由底层实现,只对标 React Router 的 BrowserRouter 的实现逻辑,完全抛弃了 HashRouter 这种哈希路由模式 —— Next.js 项目里不存在 # 号的哈希路由,也不支持 HashRouter 相关的任何特性;
  3. BrowserRouter/HashRouter 是「React 前端路由方案」,Next.js 是「全栈级路由方案」,后者的路由能力覆盖了前端+服务端,远比前者复杂。

一、BrowserRouter / HashRouter 是「纯前端路由」

首先再次明确二者的核心定位: BrowserRouter 和 HashRouter 都是 React 生态的「纯前端路由」,只作用于浏览器客户端,所有路由相关的解析、匹配、组件渲染,全部在用户的浏览器里完成,和后端/服务端没有任何关系。

  • HashRouter:基于浏览器原生hash锚点 + hashchange事件,#后的内容永远不会发给服务端;
  • BrowserRouter:基于H5的History API(pushState/replaceState) + popstate事件,干净URL,刷新会请求服务端。

二者的共性:只有「前端匹配」能力,没有服务端路由能力,本质只是「监听浏览器URL变化,渲染对应React组件」。


二、Next.js 路由的核心底层原理:只基于 History 模式(对标 BrowserRouter)

核心:Next.js 全系版本,路由底层都只实现「History 路由」这一种模式

不管是 Next.js 12 的 Pages Router,还是 Next.js 13/14 的 App Router,路由的底层实现逻辑,和 React Router 的 BrowserRouter 是同源的 —— 都是基于浏览器的 HTML5 History API (pushState / replaceState) + popstate 事件,核心特征完全一致:

  1. Next.js 的路由地址是「干净的标准URL」,格式如 https://xxx.com/home、https://xxx.com/user/1001,永远不会出现 # 号;
  2. 页面跳转时(比如<Link>组件),不会刷新整个页面,只会局部更新内容,和BrowserRouter的SPA特性一致;
  3. 路由跳转的本质是「修改浏览器地址栏URL + 更新历史记录栈」,无网络请求,符合前端路由的核心特征。

为什么 Next.js 彻底抛弃 HashRouter 哈希路由?

Next.js 作为一个面向生产级的全栈框架,HashRouter 的几个核心特性,和 Next.js 的设计理念完全冲突,所以框架从设计之初就直接剔除了哈希路由:

  1. HashRouter 的 # 号URL不美观、对SEO不友好,而Next.js主打「服务端渲染(SSR)、静态生成(SSG)」,核心优势之一就是SEO友好,哈希路由会直接废掉这个核心优势;
  2. HashRouter 是「纯前端玩法」,#后的内容无法被服务端获取,而Next.js的路由是「前后端一体化」的,服务端需要解析完整的URL路径,做SSR渲染、接口请求、权限校验等操作;
  3. 哈希路由的兼容性优势(兼容IE6/7),在现代开发中完全无意义,Next.js 本身也不兼容这类古董浏览器。

总结:Next.js 只有 History 模式的路由,没有 Hash 模式的路由,这是框架的硬性设计规则。


三、Next.js 路由 VS React Router (BrowserRouter):核心区别

这是核心知识点,二者虽然底层同源(History API),但从定位到能力,完全是两个维度的东西,差异巨大,也是面试高频考点。

区别1:路由的「实现模式」不同 —— 约定式路由 VS 声明式路由

  1. React Router (BrowserRouter):属于「声明式路由」

    • 路由规则需要手动编写代码声明:用 <Routes> + <Route> 组件,手动绑定 path 和 组件的映射关系;
    • 路由规则写在代码里,修改路由需要改代码、重新打包部署;
    • 无固定目录规范,路由和组件的存放位置可以随意定义。
  2. Next.js 路由:属于「约定式路由 / 文件系统路由」

    • 路由规则由 项目目录结构自动生成,「文件即路由」,无需编写任何路由配置代码;
    • 比如 pages/index.js → /,pages/about.js → /about,app/user/[id]/page.js → /user/1001;
    • 新增/修改路由,只需要在对应目录下新增/修改文件即可,框架自动识别,无需手写路由规则。

这是二者最核心的区别,也是 Next.js 路由最核心的特性,极大减少了路由配置的冗余代码。

区别2:路由的「运行环境」不同 —— 前后端双端路由 VS 纯前端路由

  1. React Router (BrowserRouter):仅在浏览器客户端运行

    • 所有路由的解析、匹配、组件渲染,全部发生在用户的浏览器里;
    • 服务端对路由一无所知,服务端只负责返回一个打包好的 index.html,剩下的全由前端处理;
    • 鉴权、路由拦截等逻辑,也只能在前端完成(比如受保护路由的组件封装)。
  2. Next.js 路由:浏览器客户端 + Node.js 服务端 双端运行

    • Next.js 是全栈框架,内置了 Node.js 服务端,路由的处理分为「服务端阶段」和「客户端阶段」;
    • 服务端阶段:用户第一次访问页面(比如输入URL回车),请求会先到达 Next.js 的服务端,服务端会解析URL路径、匹配对应的页面文件、做服务端渲染(SSR)、权限校验、数据请求,然后把渲染好的HTML页面返回给浏览器;
    • 客户端阶段:用户在页面内点击<Link>跳转,此时是前端路由行为,和BrowserRouter一致,无刷新局部更新,由客户端解析路由;
    • 这种「双端路由」的设计,是 Next.js 实现 SSR/SSG/ISR 这些核心渲染能力的基础。

区别3:路由的「能力边界」不同 —— 全栈路由能力 VS 仅组件渲染

  1. React Router (BrowserRouter):路由的能力非常单一,核心只有一个 → 根据URL匹配并渲染对应的React组件;

    • 没有数据请求能力,没有服务端渲染能力,没有路由级别的权限校验能力;
    • 所有额外能力(比如路由传参、受保护路由)都需要开发者基于React的钩子手动封装。
  2. Next.js 路由:路由是框架的「核心骨架」,承载了大量的全栈能力,路由和这些能力深度绑定:

    • 路由级数据请求:Pages Router 的 getServerSideProps/getStaticProps,App Router 的 async/await 直接请求数据,都是和路由绑定的,在页面渲染前完成数据请求;
    • 路由级渲染策略:同一个路由可以配置成「服务端渲染SSR」「静态生成SSG」「增量静态再生ISR」,按需选择;
    • 路由级权限校验:Pages Router 的 getServerSideProps 服务端鉴权,App Router 的 middleware.js 全局路由中间件,都是路由自带的能力;
    • 路由级缓存/预加载:Next.js 的 <Link> 组件会自动预加载目标页面的资源,提升跳转速度,这也是路由的内置特性。

区别4:路由的「刷新404问题」不同 —— 框架原生解决 VS 需要手动配置

这是一个非常实用的差异点,也是你之前学习BrowserRouter时的核心痛点:

  1. React Router (BrowserRouter):打包部署后,刷新页面大概率出现404,原因是浏览器请求了完整的URL路径,服务端没有对应的资源,必须手动配置后端(Nginx/Node)重定向到index.html;
  2. Next.js 路由:完全不存在刷新404的问题,无需任何后端配置!
    • 原因:Next.js 本身就是一个 Node.js 服务端框架,当用户刷新页面时,请求会到达 Next.js 的服务端,服务端会根据URL路径匹配对应的页面文件,然后返回渲染好的页面,服务端自己处理了所有路由的兜底逻辑;
    • 哪怕是静态打包的 Next.js 项目(next export),打包后的静态文件也会自带路由的兜底规则,部署后刷新依然不会404。

四、Next.js 两个版本的路由体系,底层原理一致(只是写法不同)

Next.js 分为 Pages Router(12及更早)和 App Router(13/14)两个版本,路由的写法差异巨大,但底层的核心原理完全不变,统一遵循以下规则:

  1. 底层都是基于 HTML5 History API,无哈希路由,URL都是干净的标准格式;
  2. 都是「文件系统路由」,文件即路由,无需手写路由配置;
  3. 都是「双端路由」,支持服务端+客户端的路由处理;
  4. 都是「History 模式」,跳转无刷新,局部更新页面。

补充:两个版本的路由核心差异(仅写法,非原理)

  1. Pages Router(pages目录):

    • 页面文件写在 pages 目录下,比如 pages/about.js → /about;
    • 动态路由用 [id].js 命名,比如 pages/user/[id].js → /user/1001;
    • 鉴权用 getServerSideProps 服务端函数,在页面渲染前做权限校验。
  2. App Router(app目录):

    • 页面文件写在 app 目录下,页面组件固定为 page.js,比如 app/about/page.js → /about;
    • 动态路由用 [id] 文件夹,比如 app/user/[id]/page.js → /user/1001;
    • 鉴权用根目录的 middleware.js 全局中间件,统一拦截所有路由请求做权限校验。

核心:不管用哪个版本,你都不用关心「路由原理」,框架已经帮你封装好了所有底层细节,你只需要按目录规范创建文件即可。


五、关键补充:Next.js 中的 <Link> 组件 VS React Router 的 <Link> 组件

你会发现,Next.js 也有 <Link> 组件,用法和 React Router 的 <Link> 几乎一样(都是 <Link href="/about">),但二者也是同源不同库:

  1. 作用一致:都是实现「无刷新路由跳转」,替代原生的<a>标签,避免页面刷新;
  2. 底层一致:都是基于 History API 修改URL,不发起网络请求;
  3. 归属不同:Next.js 的 <Link> 是框架内置组件(next/link),React Router 的 <Link> 是第三方库组件(react-router-dom);
  4. 能力不同:Next.js 的 <Link> 自带「预加载」特性,会自动预加载目标页面的资源,跳转速度更快,这是 React Router 的 <Link> 没有的。

六、总结

核心关系

  1. Next.js 的路由 不是 基于 React Router 的 BrowserRouter/HashRouter 实现的,是独立的原生路由体系;
  2. Next.js 只实现了 History 路由模式(对标 BrowserRouter),完全不支持 HashRouter 哈希路由,无 # 号URL;
  3. 二者的底层同源(都是History API),但Next.js的路由是「全栈级」,React Router是「前端级」,能力不在一个维度。

核心差异

  • React Router (BrowserRouter/HashRouter):纯前端、声明式、只有组件渲染能力 的路由方案;
  • Next.js 路由:前后端一体化、约定式、自带全栈能力 的路由方案,框架原生解决了所有前端路由的痛点。

关键结论

  1. 不用再纠结 Next.js 是否支持 HashRouter —— 不支持,也不需要支持;
  2. Next.js 的路由是「开箱即用」的,无需配置、无需安装依赖,按目录创建文件即可;
  3. Next.js 彻底解决了 BrowserRouter 的「刷新404」痛点,部署零配置;
  4. React 受保护路由、路由传参等逻辑,在 Next.js 中都有对应的实现方式,但写法完全不同(因为是两套体系)。
评论
0/100