You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:05:29