本文介绍一种简洁、可维护的模式,通过函数式导出(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 实例};
⚠️ 关键注意事项:
该方案兼顾模块化、可测试性与可读性,是 Express 官方文档推荐的高级组织方式之一,适用于中大型项目演进。