Express应用从CJS转ESM后嵌套路由报错求助
Express从CommonJS转ES Modules后嵌套路由报错排查与解决
我跟着教程做了一个带API的Express应用,现在正把它从CommonJS(CJS)转成ES Modules(ESM)。Express官方文档大多是CJS内容,参考价值有限。大部分转换完成后,嵌套路由出现了两个无法解决的错误。
应用设计背景
API包含旅行数据(tour)和旅行评论数据(review)两个集合,评论用父引用关联旅行,所以把review路由嵌套在tour路由里:router.use("/:tourId/reviews", reviewRouter),并且在review路由里设置了mergeParams: true来获取请求里的tourID。
环境
- Windows 11
- VS Code v1.83.1
- Node v18.18.0
错误信息
执行npm run start时先后出现两个错误:
旧错误
C:\[filePath]\[appName]\node_modules\express\lib\router\index.js:469 throw new TypeError('Router.use() requires a middleware function but got a ' + gettype(fn)) ^ TypeError: Router.use() requires a middleware function but got a Module at Function.use (C:\[filePath]\[appName]\node_modules\express\lib\router\index.js:469:13) at file:///C:/[filePath]/[appName]/routes/tourRoutes.js:45:8 at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
新错误
file:///C:/[filePath]/[appName]/routes/tourRoutes.js:45 router.use("/:tourId/reviews", reviewRouter); ^ ReferenceError: reviewRouter is not defined at file:///C:/[filePath]/[appName]/routes/tourRoutes.js:45:32
相关代码
tourRoutes.js
import express from "express"; import * as tourController from "../controllers/tourController.js"; import * as authController from "../controllers/authController.js"; import reviewRoutes from "./reviewRoutes.js"; const router = express.Router(); // ======================= // TOUR ROUTES router .route("/:id") .get(tourController.getTour) .patch( /* middleware */ ) .delete( /* middleware */ ); // ======================= // NESTED ROUTES // LINE 45: router.use("/:tourId/reviews", reviewRouter); export default router;
reviewRoutes.js
import express from "express"; import * as reviewController from "../controllers/reviewController.js"; import * as authController from "../controllers/authController.js"; // Allows for nested route in tourRoutes.js: const router = express.Router({ mergeParams: true }); router .route("/") .get(reviewController.getAllReviews) .post( authController.restrictTo("user"), reviewController.setTourUserId, reviewController.createReview ); // Other routers with CRUD routes export default router;
尝试过的方案
已知错误是CJS转ESM导致的,原来的CJS语法const reviewRouter = require("./reviewRoutes")能正常运行。试过修改导出导入方式,包括把reviewRouter设为默认导出后用命名导入、导出特定路由等,但都没解决问题。
解决方法
1. 修正导入变量名
核心问题是导入与使用的变量名不匹配:在tourRoutes.js里导入的是reviewRoutes,但调用时用的是reviewRouter,直接统一变量名即可:
// tourRoutes.js中修改导入语句 import reviewRouter from "./reviewRoutes.js"; // 嵌套路由代码保持不变 router.use("/:tourId/reviews", reviewRouter);
2. 确认ESM模式配置正确
确保项目已开启ESM:
- 在
package.json中添加"type": "module" - 所有模块导入必须带完整
.js后缀(ESM不允许省略后缀)
3. 排查循环导入
如果修改后仍出现got a Module错误,检查是否存在循环导入(比如tourRoutes和reviewRoutes互相引用)。若有,将共享的中间件或工具函数抽离到单独文件,避免循环依赖。
内容的提问来源于stack exchange,提问作者Marina
相关产品推荐
相关产品推荐

