一文带你搞定Nestjs项目中的配置文件(四种方案)!

2024-03-27 18:28

本文主要是介绍一文带你搞定Nestjs项目中的配置文件(四种方案)!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一文带你搞定Nestjs项目中的配置文件(四种方案)!

(妈妈再也不用担心我的学习了!认准汪枫,用最详细的步骤和保姆式教学为你答疑解惑)

前言:

应用程序通常在不同的环境中运行,根据环境的不同,应该使用不同的配置设置。例如,通常本地环境依赖于特定的数据库凭据,仅对本地 DB 实例有效,生产环境将使用一组单独的 DB 凭据。

由于配置变量会更改,所以最佳实践是将配置变量存储在环境中。

应用程序通常在不同的环境中运行,根据环境(Development,Production)的不同,应该使用不同的配置设置。

第一章😄

1.最简单的用法

使用官方为我们提供的nestconfig配置库 去解析我们的配置文件

1.1安装依赖
npm i --save @nestjs/config
1.2创建配置文件(.env)
DATABASE_USER=test
DATABASE_PASSWORD=test123
1.3配置src/app.module.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { HomeworkModule } from './homework/homework.module';
import { ConfigModule } from '@nestjs/config';// 全局导入配置模块
@Module({// 导入配置模块imports: [ConfigModule.forRoot({// 设置为全局配置 再每个模块中都可以使用isGlobal: true,}),UserModule,HomeworkModule,],controllers: [],providers: [],
})
export class AppModule {}

下面来使用src/app.controller.ts中测试:

import { Controller, Get } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AppService } from './app.service';@Controller()
export class AppController {constructor(private readonly appService: AppService,//别忘了初始化方法private configService: ConfigService,) {}@Get()getHello(): string {const dbUser = this.configService.get<string>('DATABASE_USER');console.log(dbUser); // 这里来测试return this.appService.getHello();}
}

尝试在src/user.controller.ts中使用:

import { Controller, Get, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { ConfigService } from '@nestjs/config';
@Controller('user')
export class UserController {constructor(private userService: UserService,private configService: ConfigService,) {}@Get()getUsers(): any {const DATABASE_USER = this.configService.get<string>('DATABASE_USER');console.log('获取到的数据库用户名为:', DATABASE_USER);return this.userService.getUsers();}@Post()addUsers(): any {return this.userService.addUsers();}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小结:注意如果想app下的所有子模块都能获取到这个配置文件我们需要在app.module.ts设置isGlobal: true

这种库只能实现配置文件的读取,好像不能区分开发环境去读取配置文件。

第二章😘

1.解析yml配置文件

我们将使用node中的redfile模块去完成开发环境和生产环境的配置文件获取

1.1安装依赖:
  • npm i js-yaml
  • npm i -D @types/js-yaml
  • pnpm i process
1.2创建配置文件:

在根目录下创建config文件夹在里面放上config.yml

http:port: 8080db:postgres:port: 5432sqlite:

在根目录下创建config文件夹在里面放上config.production.yml

http:host: 'localhostPRO'db:postgres:url: 'this is production postgres url'database: 'yaml-dbPRO'sqlite:database: 'sqlite.dbPRO'

在根目录下创建config文件夹在里面放上config.development.yml

http:host: 'localhostDEV'db:postgres:url: 'this is development postgres url'database: 'yaml-dbDEV'sqlite:database: 'sqlite.dbDEV'
1.3创建一个读取函数 configuration.ts
/* eslint-disable */
import { readFileSync } from 'fs';
import * as yaml from 'js-yaml';
import { join } from 'path';
import * as _ from 'lodash';
const YAML_CONFIG_FILENAME = 'config/config.yml';
const filePath = join(__dirname, '../', YAML_CONFIG_FILENAME);
const envfilePath = join(__dirname,'../',`config/config.${process.env.NODE_ENV || 'development'}.yml`,
);
const commonConfig = yaml.load(readFileSync(filePath, 'utf8'));
const envConfig = yaml.load(readFileSync(envfilePath, 'utf8'));
// 为什么要导出一个函数呢?
// 因为在Nestjs中,我们一般会将配置信息放在一个模块中,然后在其他模块中通过一个函数来获取配置信息。
// 这样做的好处是可以将配置信息和业务逻辑分离,使得代码更加清晰。
// 另外,在Nestjs中,我们一般会将配置信息放在一个单独的文件中,比如config.yml。
// 而在其他模块中,我们只需要调用这个函数就可以获取到配置信息。
export default () => {return _.merge(commonConfig, envConfig); // 读取yaml配置文件并解析为json对象返回
};

不要以为commonConfig没用 看看我的解释

在 _.merge(commonConfig, envConfig) 中,
如果envConfig和commonConfig中有相同的属性,则envConfig的属性会覆盖commonConfig的属性。
这意味着在合并后的结果中,来自envConfig的属性值会取代来自commonConfig的相应属性值。
举例来说,如果commonConfig中有一个名为serverPort的属性,而envConfig中也有一个同名的属性,
并且在调用_.merge(commonConfig, envConfig)时envConfig排在前面,则合并后的结果中serverPort的值将取自envConfig而不是commonConfig。 
1.4没用的废话 估计你也不看

这种读取函数 是否能解析呢 我们来看看源码

打开你的app.module.ts 找到imports 按住ctrl键 单机ConfigModule 打开源码 继续找到这一行

  static forRoot(options?: ConfigModuleOptions): DynamicModule;

继续按住ctrl键单机ConfigModuleOptions跳转到 该源码界面 可以看见什么

 /*** Array of custom configuration files to be loaded.* See: https://docs.nestjs.com/techniques/configuration*/
load?: Array<ConfigFactory>;

Load是什么:* 要加载的自定义配置文件数组。 那可太简单了 直接给他个json格式数组 读取就完事了呗

1.5修改package.json
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "cross-env NODE_ENV=production node dist/src/main",
1.5修改app.module.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { HomeworkModule } from './homework/homework.module';
import { ConfigModule } from '@nestjs/config';
import configuration from 'configuration'; //define the configuration file path
@Module({// 导入配置模块imports: [ConfigModule.forRoot({isGlobal: true,load: [configuration], //加载配置文件}),UserModule,HomeworkModule,],controllers: [],providers: [],
})
export class AppModule {}

尝试读取

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { DatabaseConfig } from '../types/interface';
import { ConfigService } from '@nestjs/config';
@Controller()
export class AppController {constructor(private readonly appService: AppService,private configService: ConfigService,) {}@Get()getHello(): string {const dbUser = this.configService.get<string>('DATABASE_USER');console.log('官方库的获取', dbUser); // 这里来测试console.log('yml获取配置', this.configService.get<DatabaseConfig>('db'));return this.appService.getHello();}
}
官方库的获取 Joon
yml获取配置 {postgres: {port: 5432,url: 'this is development postgres url',database: 'yaml-dbDEV'},sqlite: { database: 'sqlite.dbDEV' }
}

大家可以尝试一下 pnpm start:prod pnpm start:dev

2.解析env

本节将采用.env当公共的配置文件 同样的他和yml文件一个会进行覆盖配置项

2.1安装依赖:
  • npm i cross-env
  • npm i dotenv
2.2添加配置文件:
  • .env.development

    # DATABASE_USER=Joon(DEV)
    DATABASE_PASSWORD=123321(DEV)
    DATABASE_NAME=learn-config(DEV)
    
  • .env.production

    DATABASE_USER=Joon(PRD)
    DATABASE_PASSWORD=123321(PRD)
    DATABASE_NAME=learn-config(PRD)
    
  • .env

    DATABASE_USER=Joon(BASE)
    DATABASE_PASSWORD=123321(BASE)
    DATABASE_NAME=learn-config  (BASE)
    DATA="EVN或者PRO没用的配置"
    
2.3修改package.json
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "cross-env NODE_ENV=production node dist/src/main",

不要问我为什么重复我怕你没看第一节课就过来了 带着你重复修改一下 防止你报错

设置app.module.ts

默认是development

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { UserModule } from './user/user.module';
import * as dotenv from 'dotenv';
const envPath = `.env.${process.env.NODE_ENV || 'development'}`;
@Module({imports: [ConfigModule.forRoot({isGlobal: true,envFilePath: envPath,// 这里新增.env的文件解析load: [() => dotenv.config({ path: '.env' })],}),UserModule,],controllers: [AppController],providers: [AppService],
})
export class AppModule {}

3.解析Json配置文件😸(我的最爱)

本节采用config库去解析json文件做为nesjs的配置文件

1.安装第三方包
npm i config -S
npm i cross-env -D
2.新建 配置文件config/

default.json:

{"server": {"happy": "my default value"}
}

development.json:

{"server": {"port": 3001,"host": "localhost","username": "test","password": "test"}
}

production.json:

{"server": {"port": 3002,"host": "localhost","username": "prod","password": "prod"}
}
3.在app.controller.ts中使用:
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import * as config from 'config';@Controller()
export class AppController {constructor(private readonly appService: AppService) {}@Get()getHello(): string {const server = config.get('server');console.log(server);return this.appService.getHello();}
}
4.配置脚本:
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:prod": "cross-env NODE_ENV=production node dist/main",
5.运行结果:
npm run start:dev
获取json配置 {happy: 'my default value',port: 3001,host: 'localhost',username: 'test',password: 'test'
}npm run start:prod
获取json配置 {happy: 'my default value',port: 3002,host: 'localhost',username: 'prod',password: 'prod'
}

小结:

到这里一共亮出了四种解决配置文件方案基本在开发中够用了,大家着重选取自己喜欢的方式去配置你的api接口

我最喜欢json配置文件😃

第三章(配置验证)

配置验证,主要是指在应用程序启动时,如果没有提供所需的环境变量或不符合某些验证规则,就会抛出一个异常。@nestjs/config包实现了两种不同的方式来实现这一点。

  • Joi内置验证器。通过Joi,你可以定义一个对象模式,并根据它验证JavaScript对象
  • 一个自定义的validate()函数,它将环境变量作为输入

1.Joi

特别说明:

  • 最新版本的joi需要你运行Node v12或更高版本。旧版本的node请安装v16.1.8。这主要是因为在v17.0.2发布后,在构建的时候会出现错误。更多信息请参考其17.0.0发布说明,点击这里。
  • joi最好配合官方的@nestjs/config进行使用

步骤:

  • 安装依赖

    npm install --save joi
    
  • 定义验证Schema:

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import * as Joi from 'joi';
    import { ConfigModule } from '@nestjs/config';const envPath = `.env.${process.env.NODE_ENV || 'development'}`;@Module({imports: [ConfigModule.forRoot({envFilePath: envPath,// 这里多了一个属性:validationSchemavalidationSchema: Joi.object({NODE_ENV: Joi.string().valid('development', 'production', 'test', 'provision').default('development'),PORT: Joi.number().default(3000),DATABASE_USER: Joi.string().required()}),}),],controllers: [AppController],providers: [AppService],
    })
    export class AppModule {}
  • 验证测试

    配置错误脚本:

    "start:dev": "cross-env NODE_ENV=development PORT=toimc nest start --watch",
    

    配置正确的脚本:

    "start:dev": "cross-env NODE_ENV=development PORT=3000 nest start --watch",
    

    测试命令

    npm run start:dev
    

    错误的提示:

    [下午7:33:38] Found 0 errors. Watching for file changes./Users/macos/Projects/nestjs/nestjs-common-template/node_modules/_@nestjs_config@0.6.3@@nestjs/config/dist/config.module.js:61throw new Error(`Config validation error: ${error.message}`);^Error: Config validation error: "PORT" must be a numberat Function.forRoot (/Users/macos/Projects/nestjs/nestjs-common-template/node_modules/_@nestjs_config@0.6.3@@nestjs/config/dist/config.module.js:61:23)at Object.<anonymous> (/Users/macos/Projects/nestjs/nestjs-common-template/dist/app.module.js:21:35)at Module._compile (internal/modules/cjs/loader.js:1063:30)at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)at Module.load (internal/modules/cjs/loader.js:928:32)at Function.Module._load (internal/modules/cjs/loader.js:769:14)at Module.require (internal/modules/cjs/loader.js:952:19)at require (internal/modules/cjs/helpers.js:88:18)at Object.<anonymous> (/Users/macos/Projects/nestjs/nestjs-common-template/dist/main.js:4:22)at Module._compile (internal/modules/cjs/loader.js:1063:30)
    

    或者修改.env.development中的配置信息:

    DATABASE_USER=
    DATABASE_PASSWORD=test123
    

    错误提示:

    /Users/macos/Projects/nestjs/nestjs-common-template/node_modules/_@nestjs_config@0.6.3@@nestjs/config/dist/config.module.js:61throw new Error(`Config validation error: ${error.message}`);^Error: Config validation error: "DATABASE_USER" is not allowed to be emptyat Function.forRoot (/Users/macos/Projects/nestjs/nestjs-common-template/node_modules/_@nestjs_config@0.6.3@@nestjs/config/dist/config.module.js:61:23)at Object.<anonymous> (/Users/macos/Projects/nestjs/nestjs-common-template/dist/app.module.js:21:35)at Module._compile (internal/modules/cjs/loader.js:1063:30)at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)at Module.load (internal/modules/cjs/loader.js:928:32)at Function.Module._load (internal/modules/cjs/loader.js:769:14)at Module.require (internal/modules/cjs/loader.js:952:19)at require (internal/modules/cjs/helpers.js:88:18)at Object.<anonymous> (/Users/macos/Projects/nestjs/nestjs-common-template/dist/main.js:4:22)at Module._compile (internal/modules/cjs/loader.js:1063:30)
    

结论:使用Joi可以很方便对传入应用程序的参数进行验证,可以限制传入的数据类型。

除了上面写的验证以外,还可以加入以下属性来验证输入的命令参数

@Module({imports: [ConfigModule.forRoot({envFilePath: envPath,validationSchema: Joi.object({NODE_ENV: Joi.string().valid('development', 'production', 'test', 'provision').default('development'),PORT: Joi.number().default(3000),DATABASE_USER: Joi.string().required()}),validationOptions: { // 这里加allowUnknown: false,abortEarly: true,},}),],controllers: [AppController],providers: [AppService],
})
export class AppModule {}

@nestjs/config包使用的默认设置是:

  • allowUnknown:控制是否允许在环境变量中使用未知键。默认为true;
  • abortEarly:如果为true,则在第一个错误时停止验证;如果为false,则返回所有错误。默认值为false;

注意上面的Joi的用法:

  • 主要是校验process.env传入的参数
  • 主要是校验envFilePath初次加载的时候的参数

2.class-validator

步骤:

  • 安装依赖class-validatorclass-transformer

    npm i class-validator class-transformer
    
  • 配置效验文件src/env.validation.ts

    import { plainToClass } from 'class-transformer';
    import { IsEnum, IsNumber, validateSync } from 'class-validator';enum Environment {Development = "development",Production = "production"
    }class EnvironmentVariables {@IsEnum(Environment)NODE_ENV: Environment;@IsNumber()PORT: number;
    }export function validate(config: Record<string, unknown>) {const validatedConfig = plainToClass(EnvironmentVariables,config,{ enableImplicitConversion: true },);const errors = validateSync(validatedConfig, { skipMissingProperties: false });if (errors.length > 0) {throw new Error(errors.toString());}return validatedConfig;
    }
    
  • 调整app.module.ts文件

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { ConfigModule } from '@nestjs/config';
    import { validate } from './env.validation';const envPath = `.env.${process.env.NODE_ENV || 'development'}`;@Module({imports: [ConfigModule.forRoot({envFilePath: envPath,validate,}),],controllers: [AppController],providers: [AppService],
    })
    export class AppModule {}
    

与使用Joi验证结果一致。

总结 :

  • 使用第三方的包config,可以方便的读取配置信息,但是校验却需要在读取的位置来加,对于不需要验证,而需要全局使用的配置项可以使用这种方式;

  • 官方的@nestjs/config可以方便的导入.env的文件,同时结合js-yaml也可以导入yaml格式的配置。

    配置灵活,而且可以配合验证工具Joi进行参数的验证(推荐)

    自定义的校验第三方包class-validator这里只是冰山一角,后面在学习数据验证的时候还会使用到它;

这篇关于一文带你搞定Nestjs项目中的配置文件(四种方案)!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/852992

相关文章

Nginx实现高并发的项目实践

《Nginx实现高并发的项目实践》本文主要介绍了Nginx实现高并发的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用最新稳定版本的Nginx合理配置工作进程(workers)配置工作进程连接数(worker_co

Java嵌套for循环优化方案分享

《Java嵌套for循环优化方案分享》介绍了Java中嵌套for循环的优化方法,包括减少循环次数、合并循环、使用更高效的数据结构、并行处理、预处理和缓存、算法优化、尽量减少对象创建以及本地变量优化,通... 目录Java 嵌套 for 循环优化方案1. 减少循环次数2. 合并循环3. 使用更高效的数据结构4

Spring AI集成DeepSeek三步搞定Java智能应用的详细过程

《SpringAI集成DeepSeek三步搞定Java智能应用的详细过程》本文介绍了如何使用SpringAI集成DeepSeek,一个国内顶尖的多模态大模型,SpringAI提供了一套统一的接口,简... 目录DeepSeek 介绍Spring AI 是什么?Spring AI 的主要功能包括1、环境准备2

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

Python中配置文件的全面解析与使用

《Python中配置文件的全面解析与使用》在Python开发中,配置文件扮演着举足轻重的角色,它们允许开发者在不修改代码的情况下调整应用程序的行为,下面我们就来看看常见Python配置文件格式的使用吧... 目录一、INI配置文件二、YAML配置文件三、jsON配置文件四、TOML配置文件五、XML配置文件

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

一文详解如何在Python中使用Requests库

《一文详解如何在Python中使用Requests库》:本文主要介绍如何在Python中使用Requests库的相关资料,Requests库是Python中常用的第三方库,用于简化HTTP请求的发... 目录前言1. 安装Requests库2. 发起GET请求3. 发送带有查询参数的GET请求4. 发起PO

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

Python中常用的四种取整方式分享

《Python中常用的四种取整方式分享》在数据处理和数值计算中,取整操作是非常常见的需求,Python提供了多种取整方式,本文为大家整理了四种常用的方法,希望对大家有所帮助... 目录引言向零取整(Truncate)向下取整(Floor)向上取整(Ceil)四舍五入(Round)四种取整方式的对比综合示例应

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤