CommonJS 通过模块缓存机制实现配置共享:导出固定对象适用于静态配置,导出工厂函数适用于动态场景;应避免污染全局、重复初始化或硬编码路径,确保配置一致可测。

CommonJS 本身没有“全局配置模块”的概念,也不鼓励把配置挂到 global 或 process 上。真正的做法是:把配置封装成一个可复用、可注入、带缓存的独立模块,通过 module.exports 导出单一配置对象或工厂函数,让所有需要的地方 require 同一份实例 —— 这就是事实上的“全局共享”,且安全、可控、可测试。
导出固定配置对象(适合静态配置)
适用于数据库地址、API 基础路径、日志等级等启动后不再变更的设置。
- 创建
config/index.js,一次性读取并导出:
const fs = require('fs');
// 合并默认 + 环境变量 + 配置文件
const defaultConfig = {
port: 3000,
env: process.env.NODE_ENV || 'development'
};
try {
const envConfigPath = path.join(__dirname, `${defaultConfig.env}.json`);
if (fs.existsSync(envConfigPath)) {
const envConfig = JSON.parse(fs.readFileSync(envConfigPath, 'utf8'));
module.exports = { ...defaultConfig, ...envConfig };
} else {
module.exports = defaultConfig;
}
} catch (err) {
console.warn('加载环境配置失败,使用默认配置');
module.exports = defaultConfig;
}
- 在任意文件中直接使用:
const config = require('./config');
多次 require 返回的是同一份引用(CommonJS 缓存机制保证),不会重复解析。
导出配置工厂函数(适合需动态初始化的场景)
当配置依赖运行时参数(如命令行参数、服务发现结果)或需延迟加载(如从远程拉取)时,用工厂函数更灵活。
- 例如
config/create.js:
const { host, port } = options;
return {
apiUrl: `http://${host || 'localhost'}:${port || 8080}/api`,
timeout: options.timeout ?? 5000
};
};
- 在应用入口统一创建一次,再传给各模块:
const createConfig = require('./config/create');<br>const config = createConfig({ host: 'api.example.com', port: 443 });<br>app.use('/user', require('./routes/user')(config));
避免常见陷阱
- 不挂 global.config:污染全局命名空间,破坏模块隔离,单元测试难 mock;
- 不每次 require 都 new 一个对象:会导致配置不一致,比如数据库连接池被重复初始化;
-
不硬编码路径:用
path.join(__dirname, ...)而非相对路径,防止被 symlink 或不同工作目录调用时出错; - 不忽略缓存机制:CommonJS 自动缓存 module.exports,这是实现“单例共享”的底层保障,无需额外处理。
配合框架使用的建议
- Express/Fastify:在 app 初始化阶段加载 config,通过
app.set('config', config)或中间件挂载到 req; - 数据库连接(如 mongoose):只在 config 模块里定义连接选项,实际连接操作放在单独的 db.js 中,导出已连接的实例;
- 环境变量优先级:process.env > config/{env}.json > 默认值,保持本地开发与部署一致性。


















