Nestjs框架: @nestjs/config 配置模块详解与实践
配置模块基础使用
在 NestJS 中,我们通常使用 @nestjs/config
模块来管理应用的配置信息。该模块基于 dotenv
,可以轻松地从 .env
或 .env.development
、.env.production
等文件中加载环境变量。
- 安装模块
pnpm install @nestjs/config
- 导入并全局注册
在根模块 AppModule
中导入并注册配置模块:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';@Module({imports: [ConfigModule.forRoot({isGlobal: true, // 全局注册,跨模块可用}),],
})
export class AppModule {}
注意:如果不设置 isGlobal: true
,则需要在每个使用配置的模块中手动导入 ConfigModule
。
配置文件的加载机制
- 基础
.env
文件
.env
文件采用键值对方式定义环境变量:
DB=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
- 多环境配置文件
可以为不同环境创建对应的 .env
文件:
.env.development
.env.production
ConfigModule.forRoot({envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,
});
这样可以根据 NODE_ENV
自动加载对应环境的配置文件
跨模块使用配置服务
配置服务 ConfigService
通常在根模块中注册后使用。跨模块使用时需确保:
- 使用
isGlobal: true
(推荐) - 或手动在子模块中导入
ConfigModule
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { UserController } from './user.controller';@Module({imports: [ConfigModule], // 手动导入controllers: [UserController],
})
export class UserModule {}
配置读取与使用
- 在控制器中使用
import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';@Controller('user')
export class UserController {constructor(private configService: ConfigService) {}@Get()getUsers() {const db = this.configService.get('DB');console.log('DB:', db);return { db };}
}
- 使用枚举封装键名(推荐)
// config.enum.ts
export enum ConfigEnum {DB = 'DB',DB_HOST = 'DB_HOST',
}// user.controller.ts
import { ConfigEnum } from './config.enum';const db = this.configService.get(ConfigEnum.DB);
进阶用法:多文件加载与共享配置
可以通过 load
方法加载多个配置文件,实现配置共享:
import * as dotenv from 'dotenv';
import * as fs from 'fs';ConfigModule.forRoot({load: [() => {const config = dotenv.parse(fs.readFileSync('.env'));return config;},],
});
也可以结合 .env.development
和 .env.production
使用:
ConfigModule.forRoot({envFilePath: [`.env.${process.env.NODE_ENV}`,'.env'],
});
这样优先读取 .env.[NODE_ENV]
,再读取 .env
。
配置校验(Validation)
为了防止错误配置,我们可以使用 Joi 库对配置进行校验。
- 安装 Joi
pnpm install joi
- 定义验证规则
import * as Joi from 'joi';const validationSchema = Joi.object({DB: Joi.string().required(),DB_HOST: Joi.string().ip(),DB_PORT: Joi.number().default(3306).valid(3306, 3307),NODE_ENV: Joi.string().valid('development', 'production'),
});
- 启用校验
ConfigModule.forRoot({validationSchema,
});
- 示例验证失败
如果 .env.development
中设置了错误值:
DB_PORT=abc
启动时将抛出错误:"DB_PORT" must be a number
高级技巧:自定义校验规则与正则表达式
- 使用正则匹配
DB_URL: Joi.string().pattern(/https:\/\/.*\.example\.com/)
- 自定义校验函数
myField: Joi.any().custom((value, helpers) => {if (value !== 'validValue') {throw new Error('Invalid value');}return value;
});
常见问题与解决方案
- 配置未生效
- 检查
.env
文件路径是否正确 - 检查
process.env.NODE_ENV
是否设置 - 确保
ConfigModule
已正确导入
- 校验失败但未抛出错误
- 确保
validationSchema
正确绑定 - 检查是否在
load
方法中覆盖了配置导致校验失效
- 全局配置未生效
- 确保
isGlobal: true
设置正确 - 检查模块是否被正确导入
完整配置示例代码
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
import * as dotenv from 'dotenv';
import * as fs from 'fs';@Module({imports: [ConfigModule.forRoot({isGlobal: true,envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,validationSchema: Joi.object({DB: Joi.string().required(),DB_HOST: Joi.string().ip(),DB_PORT: Joi.number().default(3306),NODE_ENV: Joi.string().valid('development', 'production'),}),load: [() => {const config = dotenv.parse(fs.readFileSync('.env'));return config;},],}),],
})
export class AppModule {}
总结
- 使用
@nestjs/config
模块,可以统一管理环境变量,提升项目可维护性。 - 跨模块使用时建议开启
isGlobal: true
,避免重复导入。 - 通过
envFilePath
指定多环境配置文件,灵活应对开发、测试、生产环境。 - 使用
Joi
进行配置校验,可有效防止错误配置导致的运行时异常。 - 合理使用
load
方法加载共享配置,避免冗余配置。
建议:将配置项集中管理,如使用枚举、配置校验、统一路径等方式,提升代码的可读性与健壮性。
如需进一步了解配置模块与 Joi 的详细用法,可参考如下官方文档:
- NestJS Config Module
- Joi Validation