一文带你搞定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

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

JavaFX应用更新检测功能(在线自动更新方案)

JavaFX开发的桌面应用属于C端,一般来说需要版本检测和自动更新功能,这里记录一下一种版本检测和自动更新的方法。 1. 整体方案 JavaFX.应用版本检测、自动更新主要涉及一下步骤: 读取本地应用版本拉取远程版本并比较两个版本如果需要升级,那么拉取更新历史弹出升级控制窗口用户选择升级时,拉取升级包解压,重启应用用户选择忽略时,本地版本标志为忽略版本用户选择取消时,隐藏升级控制窗口 2.

SpringBoot项目是如何启动

启动步骤 概念 运行main方法,初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量,配置信息创建SpringApplication上下文预初始化上下文,将启动类作为配置类进行读取调用 refresh 加载 IOC容器,加载所有的自动配置类,创建容器在这个过程