前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库express.Router 模块化路由 路径前缀
全栈全栈开发Express 服务

如何用 express.Router 把路由拆成可挂载模块,路径前缀如何继承?

把路由封装成 express.Router 实例,再用 app.use('/api', router) 挂载,router 内的路径会自动带上 /api 前缀,从而把路由表切成可插拔模块。

前端进阶之旅 · 一题精讲更新于 2026.09.05
全栈开发#Express 服务#路由
先看核心答案
理解线索

Router 挂载机制

  1. 迷你应用Router 有独立中间件栈和路由表
  2. 路径拼接挂载点 + router 内部路径形成最终路径
  3. 根路径router 的 '/' 匹配挂载点路径本身

注意 app.use 路径不限层级,router 内部无需感知前缀。

核心回答

先记住这个答案

Router 是一个完整的中间件和路由系统,可视为迷你应用。在 app.use(path, router) 中,path 成为 router 内所有路由的前缀。例如 router.get('/home') 挂载到 '/api' 后对应 '/api/home'。router 内部无需感知前缀,Express 在匹配时会自动拼接。若父路径含参数,需设置 mergeParams 才能访问父路径参数。

  • Router 是可独立挂载的迷你路由系统
  • 路径前缀由 app.use 的第一个参数决定
  • 父路径参数需 mergeParams 才能取到

Router 如何获得前缀

express.Router() 返回一个独立的路由容器,它内部可以注册中间件和路由处理函数。当通过 app.use('/api', router) 挂载时,Express 会把所有发给 /api 的请求交给 router 处理,且路由器并不需要知道前缀。它的每个路由只定义相对路径,最终匹配由挂载点和相对路径拼接而成。

例如 router.get('/product') 挂载到 /api 后,实际匹配 GET /api/product;而 router.get('/') 则匹配 GET /api。Express 内部将挂载点与路由路径拼接成完整路径模式,并自动处理斜杠边界。在 router 内部,req.url 会被裁剪掉挂载前缀,因此 router 内的路径匹配是基于相对路径的。

这种机制让 Router 成为可复用的中间件层。你可以在一个 router 中定义多个子路径,而无须担心外部挂载的上下文,前缀完全由根应用控制,这为代码解耦提供了基石。

拆分 REST 路由的实际场景

假设一个服务有用户和订单两组资源,每组有若干接口。若全部写进 app.js 会难以维护。可以创建 userRouter.js,内部只写 router.get('/profile')、router.get('/orders') 等相对路径。然后 app.use('/users', userRouter) 和 app.use('/orders', orderRouter)。

这里要注意的是:用户相关接口挂 /users 前缀,订单相关挂 /orders。router 内部不需要重复写前缀。若某个资源需要多级路径,例如访问 GET /users/:userId/orders,可挂载 '/users',router 内定义 '/:userId/orders',此时 :userId 是 router 内部参数,可直接在 req.params 中获取;只有当父路径本身带参数(如 app.use('/users/:userId', router) 且 router 内定义 '/orders')时,默认无法在 router 内访问父路径的 :userId,需设置 { mergeParams: true } 才能取到。

实际决策:是按资源模块拆分还是按业务域拆分。每个模块挂不同前缀,接口结构清晰,也方便为特定前缀加验证中间件,如 app.use('/admin', adminAuth, adminRouter)。

前缀拼接的失效条件

当父路由本身含路径参数,如 app.use('/users/:userId', router) 时,router 内部默认无法在 req.params 中读取 :userId,除非传入 { mergeParams: true }。若不设置,router 内 req.params 仅包含自己路由定义的参数,这是 Express 的默认安全设计,以避免参数名冲突。

另外,若将同一 router 多次挂载到不同前缀,如 app.use('/a', router) 和 app.use('/b', router),router 内的路由会同时响应两个前缀。这通常不符合预期,因为模块通常针对单一前缀;若确实需要多前缀复用,应显式创建多个 Router 实例或使用工厂函数生成。

还需注意挂载顺序:app.use 按声明顺序处理,若前面有 app.use('/', someMiddleware) 可能拦截请求,但不会影响路径匹配,只影响是否执行后续挂载。

回答前,多想一步

容易答错的地方

误认为 Router 必须是单独文件
有人认为必须把 router 导出成独立模块,其实 express.Router 只是对象,可以在任意模块中创建再挂载。拆分核心诉求是代码组织,路径前缀由 app.use 决定,与文件结构无关。
在 router 内部写完整前缀
有些人在 router 内部写完整路径,如 router.get('/api/user'),再挂载到 '/',这样虽然能工作,但违背模块化初衷。正确做法是 router 只写相对路径,让 app.use 统一控制前缀,便于迁移与复用。
试着用自己的话回答

面试官还会怎么问?

app.use('/api', router1, router2) 会怎样?

app.use 可接受多个处理函数,会依次执行。但通常每个 router 设计为处理完整请求,因此连续挂载多个 router 没有实际意义;若需先做过滤,应显式写中间件函数再调用 router。

router 内部的中间件路径如何匹配?

router.use() 未给路径时匹配所有进入该 router 的请求;若给出路径如 router.use('/admin'),则匹配挂载点 + '/admin' 起始的请求。这与路由定义保持一致。

Router 还支持哪些路径配置选项?

常见有 caseSensitive、strict 等同 app 设置。mergeParams 用于访问父路由参数。它们影响 router 内部的路径匹配行为,需按实际需求去设置。

从一道题,走向一组知识

把知识连起来

Express 服务

Express 中 app.use() 和 router.use() 挂载中间件有什么实际差异?

同属「Express 服务」专题,接着看 Express app.use 与 router.use 区别 在具体场景中的处理方式。

Express 服务

Express 中间件既不发响应也不调用 next() 会导致什么后果,如何排查?

同属「Express 服务」专题,接着看 Express 中间件忘记调用 next 请求挂起 在具体场景中的处理方式。

参考资料

  • Routing

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. Router 如何获得前缀
  3. 拆分 REST 路由的实际场景
  4. 前缀拼接的失效条件
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑