
本文介绍一种简洁、可维护的模式,通过函数式导出(function-based export)将全局配置(如 api 基础 url)从主应用文件安全、显式地注入到模块化路由文件中,避免全局变量或重复定义。
本文介绍一种简洁、可维护的模式,通过函数式导出(function-based export)将全局配置(如 api 基础 url)从主应用文件安全、显式地注入到模块化路由文件中,避免全局变量或重复定义。
在 Express 多路由项目中,为保持代码清晰与可维护性,通常将各路由逻辑拆分为独立文件(如 routes/test.js),并通过 app.use() 挂载。但当多个路由需共用同一配置(如 url = "https://example.com/v1"),直接在路由文件中硬编码会破坏单一数据源原则;而使用全局变量(如 global.url)则违背模块封装性,且不利于测试与扩展。
推荐做法是采用 工厂函数模式(Factory Function Pattern):将路由模块导出为一个接收配置参数的函数,返回配置完成的 Router 实例。这样既保证依赖显式化,又支持灵活复用与单元测试。
✅ 正确实现如下:
app.js 中初始化并传参:
const express = require("express");
const app = express();
const port = 3000;
const url = "https://example.com/v1";
// 将 url 作为参数传入路由工厂函数
const testRouter = require("./routes/test")(url);
app.use(express.json());
app.use("/test", testRouter); // 注意:必须调用 app.use() 挂载路由
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});routes/test.js 中定义可配置路由:
const express = require("express");
const router = express.Router();
// 导出工厂函数,接收外部配置
module.exports = (baseUrl) => {
// 可选:添加共享中间件(如日志)
router.use((req, res, next) => {
console.log("[Test Router] Time:", Date.now());
next();
});
// 使用传入的 baseUrl
router.post("/", (req, res) => {
console.log("Base URL used:", baseUrl);
res.json({ success: true, apiBaseUrl: baseUrl });
});
return router; // 必须返回配置后的 router 实例
};⚠️ 关键注意事项:
- 路由文件必须导出函数(而非直接导出 router),否则无法接收参数;
- app.use() 的挂载语句不可省略,且路径前缀(如 /test)应与业务语义一致;
- 若需共享多个值(如 url, timeout, authToken),可统一传入一个配置对象:require("./routes/test")({ url, timeout: 5000 });
- 此模式天然支持环境隔离——例如开发/生产环境可传入不同 baseUrl,无需条件判断。
该方案兼顾模块化、可测试性与可读性,是 Express 官方文档推荐的高级组织方式之一,适用于中大型项目演进。



















