NestJs 的 项目配置 学习

应用程序通常运行在不同的环境中。根据环境的不同,应使用不同的配置设置。例如,通常本地环境依赖于特定的数据库凭据,仅对本地数据库实例有效。生产环境将使用一组单独的数据库凭据。由于配置变量发生变化,最佳实践是将配置变量存储在环境中。

外部定义的环境变量通过全局变量在 Node.js 中可见 process.env。我们可以尝试通过在每个环境中单独设置环境变量来解决多环境的问题。这很快就会变得笨拙,特别是在需要轻松模拟和/或更改这些值的开发和测试环境中。

在 Node.js 应用程序中,通常使用.env 文件来保存键值对,其中每个键代表一个特定值,以代表每个环境。在不同的环境中运行应用程序只需交换正确的.env 文件即可。

在 Nest 中使用此技术的一个好方法是创建一个 ConfigModule 公开 ConfigService 加载适当.env 文件的 。虽然您可以选择自己编写这样的模块,但为了方便起见,Nest 提供了@nestjs/config 开箱即用的包。我们将在当前章节中介绍这个包。

安装

要使用 NestJs 提供的开箱即用的配置功能,我们必须先要安装所需插件:

npm i --save @nestjs/config

说明:@nestjs/config包内部使用了 dotenv。

开始使用

当我们安装好@nestjs/config插件后,我们就可以在AppModule中引入ConfigModule并使用.forRoot()方法对配置文件进行相应的处理。具体的代码实例如下:

import { Module } from "@nestjs/common";
import { CommodityModule } from "./module/commodity.module";
import { AccountModule } from "./module/account.module";
import { ConfigModule } from "@nestjs/config";@Module({imports: [CommodityModule, AccountModule, ConfigModule.forRoot()],
})
export class AppModule {}

上述的例子中系统会将从项目根目录加载并解析 .env 文件,并且把.env文件中的键/值对分配给process.env并对环境变量进行合并,最终会将合并的结果储存在ConfigService的私有结构中。

上述的例子中我们可以看到我们在 AppModule 中声明了forRoot()方法,forRoot 主要是会把 ConfigService 注册到系统中,并且 ConfigService 会提供get()方法来让我们解析和合并配置变量。在合并配置变量的时候总会遇到同名的请求,这时@nestjs/config 会依赖于 dotenv来解决重名的情况。而解决冲突的优先级如下:

  • 运行时环境变量优先
  • .env 配置文件

自定义环境文件路径

在 NestJs 中默认情况,应用程序会在根目录下查找.env的文件作为环境配置文件来加载,假如需要重新制定另外一个配置文件的话,可以在forRoot方法中使用envFilePath属性来进行声明,具体的例子如下:

ConfigModule.forRoot({envFilePath: ".env.development",
});

您还可以为.env 文件指定多个路径,如下所示:

ConfigModule.forRoot({envFilePath: [".env.development.local", ".env.development"],
});

如果在多个文件中找到一个变量,则第一个优先。

禁用环境变量加载

如果您不想加载.env 文件,而是想简单地从运行时环境访问环境变量(与 OS shell 导出一样 export DATABASE_USER=test),请将选项对象的 ignoreEnvFile 属性设置为 true,如下所示:

ConfigModule.forRoot({ignoreEnvFile: true,
});

全局使用模块

当你要在其他模块中获取环境配置变量的话,可以在其他模块中导入ConfigModule(与任何 Nest 模块的标准一样)。或者可以使用isGlobal属性开启全局属性,这样一旦设置为 true 后,配置文件的参数就会加载到根模块上,就不用再导入其他模块,这样就可以直接使用。开启全局的实例如下:

ConfigModule.forRoot({isGlobal: true,
});

自定义配置文件

当项目比较大的时候,我们可能会配置很多参数,例如多数据库、缓存、集群等相关的数据。这样把所有相关配置都写在一个文件中不利于后期维护,所以我们可以利用自定义配置文件来返回嵌套配置对象。在 NestJs 中它允许我们按照功能对相关配置进行设置(例如:数据库相关设置)分组,并将相关设置放在不同的文件中进行单独管理。

自定义配置文件导出返回配置对象的工厂函数。配置对象可以是任意嵌套的纯 JavaScript 对象。由于您控制返回的配置对象,因此您可以添加任何所需的逻辑以将值转换为适当的类型、设置默认值等。具体实例如下:

export default () => ({port: parseInt(process.env.PORT ? process.env.PORT : "8080", 10) || 3000,database: {host: process.env.DATABASE_HOST,port:parseInt(process.env.DATABASE_PORT ? process.env.DATABASE_PORT : "3306",10) || 5432,},
});

加载自定义配置文件,可以在forRoot方法中进行加载:

@Module({imports: [CommodityModule,AccountModule,ConfigModule.forRoot({load: [configuration],}),],
})
export class AppModule {}

注意:分配给属性的值 load 是一个数组,允许您加载多个配置文件(例如 load: [databaseConfig, authConfig])

除了可以使用使用对象的格式外还可以使用YAML文件来实现配置文件的编写,要使用之前我们必须安装相关的依赖,具体安装依赖如下:

$ npm i js-yaml
$ npm i -D @types/js-yaml

YAML 文件实例:

http:host: "localhost"port: 8080db:postgres:url: "localhost"port: 5432database: "yaml-db"sqlite:database: "sqlite.db"

加载解析 YAML 文件的 JS 代码如下:

import { readFileSync } from "fs";
import * as yaml from "js-yaml";
import { join } from "path";const YAML_CONFIG_FILENAME = "config.yaml";export default () => {return yaml.load(readFileSync(join(__dirname, YAML_CONFIG_FILENAME), "utf8")) as Record<string, any>;
};

使用 ConfigService

当我们要使用ConfigService的话,首先需要注入ConfigService。与其他提供者一样,我们要先把ConfigModule导入到对应的模块中然后才能使用,除非我们把开启了全局的配置。

具体实例如下:

// 在CommodityModule中注入ConfigModule
@Global()
@Module({imports: [ConfigModule],controllers: [CommodityController],providers: [CommodityService],exports: [CommodityService],
})
export class CommodityModule {}// 在控制器中注入ConfigService
@Controller("commodity")
@UseInterceptors(LoggingInterceptor, TransformInterceptor)
export class CommodityController {constructor(private commodityService: CommodityService,private configService: ConfigService) {}@Post("/save")saveCommodity(@Body() commodity: Commodity) {console.log(this.configService.get<string>("DATABASE_USER"));console.log(this.configService.get<string>("DATABASE_PASSWORD"));console.log(this.configService.get<number>("port"));this.commodityService.create(commodity);}
}

如上所示,使用 configService.get() 方法通过传递变量名称来获取一个简单的环境变量。您可以通过传递类型来进行 TypeScript 类型提示,如上所示(例如 get(…))。get() 方法还可以遍历嵌套的自定义配置对象(通过自定义配置文件创建)。

您还可以使用接口作为类型提示来获取整个嵌套的自定义配置对象,具体实例如下:

interface DatabaseConfig {host: string;port: number;
}const dbConfig = this.configService.get<DatabaseConfig>("database");
const port = dbConfig.port;

get()方法其实可以传入两个参数,第二个参数是可选的,它的作用主要是定义默认值,当键值不存在的时候就会返回默认值。具体实例如下:

const dbHost = this.configService.get<string>("database.host", "localhost");

ConfigService 有两个可选的泛型(类型参数)。

  • 第一个是帮助防止访问不存在的配置属性。使用方法如下图所示:
//
interface EnvironmentVariables {PORT: number;TIMEOUT: string;
}constructor(private configService: ConfigService<EnvironmentVariables>) {const port = this.configService.get('PORT', { infer: true });const url = this.configService.get('URL', { infer: true }); // URL参数并不属于配置文件中的参数,这里会报错
}

infer属性为 true 时,configService 的 get 方法会自动根据接口定义的参数类型进行判断,假如不符合类型的话就会报错。configService 的 get 方法除了能够检测字符串外还可以检测对象的属性类型,例如:

constructor(private configService: ConfigService<{ database: { host: string } }>) {const dbHost = this.configService.get('database.host', { infer: true });
}
  • 第二个泛型依赖于第一个泛型,充当 TS 类型断言,当设置为 tue 后,TS 会在编写代码的时候进行类型检测,当类型不匹配的时候则会报错。
constructor(private configService: ConfigService<{ PORT: number }, true>) {const port = this.configService.get('PORT', { infer: true });

配置命名空间

在上述例子中我们使用的是对象嵌套关系来组织配置的,在 NestJS 中还提供了另外一种方式来帮我们分类管理配置,那就是命名空间。具体实例如下:

import { registerAs } from "@nestjs/config";export default registerAs("database", () => ({host: process.env.DATABASE_HOST,port: process.env.DATABASE_PORT || 5432,
}));

使用命名空间来实现自定义配置后,参数的合并规则和加载方式都跟上述的自定义方式保持一致。要获取数据的话,可以使用命名空间名称.对应的属性来获取。具体的实例如下:

const dbHost = this.configService.get<string>("database.host");

在上述的例子中我们使用configService对象来获取配置参数,但是当我们使用命名空间方式来定义的配置文件的时候我们就可以直接注入命名空间来获取数据。具体的实例如下:

@Controller("commodity")
export class CommodityController {constructor(private commodityService: CommodityService,@Inject(databaseConfig.KEY)private dbConfig: ConfigType<typeof databaseConfig>) {}@Post("/save")saveCommodity(@Body() commodity: Commodity) {console.log(this.dbConfig.host);this.commodityService.create(commodity);}
}

缓存环境变量

由于访问 process.env 可能会很慢,因此您可以设置传递给 ConfigModule.forRoot() 的选项对象的缓存属性,以提高 ConfigService#get 方法在处理 process.env 中存储的变量时的性能。具体设置实例如下:

ConfigModule.forRoot({cache: true,
});

部分注册

到目前为止,我们已经在根模块(例如 AppModule)中处理了配置文件和使用 forRoot() 方法。也许您有一个更复杂的项目结构,特定于功能的配置文件位于多个不同的目录中。在 NestJS 中还提供了一种称为部分注册的功能,而不是在根模块中加载所有这些文件,它仅引用与每个功能模块关联的配置文件。如果要使用此功能的话,主要使用 forFeature() 静态方法来执行此部分注册。具体实例如下:

import databaseConfig from "./config/database.config";@Module({imports: [ConfigModule.forFeature(databaseConfig)],
})
export class DatabaseModule {}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/30172.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第48节:cesium 面交集计算(含源码+视频)

结果示例: 完整源码: <template><div class="viewer"><vc-viewer @ready="ready" :logo="false"><vc-navigation

docker版jxTMS使用指南:使用jxTMS采集数据之一

本文讲解了如何jxTMS的数据采集与处理框架并介绍了如何用来采集数据&#xff0c;整个系列的文章请查看&#xff1a;docker版jxTMS使用指南&#xff1a;4.4版升级内容 docker版本的使用&#xff0c;请查看&#xff1a;docker版jxTMS使用指南 4.0版jxTMS的说明&#xff0c;请查…

Unity之ShaderGraph 节点介绍 Utility节点

Utility 逻辑All&#xff08;所有分量都不为零&#xff0c;返回 true&#xff09;Any&#xff08;任何分量不为零&#xff0c;返回 true&#xff09;And&#xff08;A 和 B 均为 true&#xff09;Branch&#xff08;动态分支&#xff09;Comparison&#xff08;两个输入值 A 和…

15 款最佳建筑渲染软件,适用于 Windows、macOS,免费和付费版本

3D 建模和渲染在建筑行业的各种项目的推广和营销中发挥着非常重要的作用。建筑公司使用 3D 建模和渲染、3D 建筑动画和演练来展示他们的设计。房地产效果图帮助代理商让客户清楚地了解建筑设计、纹理、灯光效果和环境情况。这是非常有价值的&#xff0c;并且在销售设计时提供了…

uniapp封装手写签名

组件代码 cat-signature <template><view v-if"visibleSync" class"cat-signature" :class"{visible:show}" touchmove.stop.prevent"moveHandle"><view class"mask" tap"close" /><view c…

解决MAC M1处理器运行Android protoc时出现的错误

Protobuf是Google开发的一种新的结构化数据存储格式&#xff0c;一般用于结构化数据的序列化&#xff0c;也就是我们常说的数据序列化。这个序列化协议非常轻量级和高效&#xff0c;并且是跨平台的。目前&#xff0c;它支持多种主流语言&#xff0c;比传统的XML、JSON等方法更具…

python采集淘宝整店商品 json格式

竞争优势&#xff1a;通过采集淘宝整店商品&#xff0c;可以获取到同一行业或同一类别的竞争对手的商品信息。这使得你可以更好地了解市场上的产品&#xff0c;了解竞争对手的定价、销售策略和产品特点&#xff0c;从而更好地制定自己的营销策略和定价策略。在竞争激烈的市场中…

类和对象的学习

类和对象说明 类的属性和方法 类的入门案例 //类名 public class school {//属性String name; //名称int jsNumber; //教室数目int jfNumber;//机房数目//方法public void show(){System.out.println("名称: " name "教室数目" jsNumber " , 机房数…

设计模式——设计模式以及六大原则概述

设计模式代表有经验的面向对象软件开发人员使用的最佳实践。 设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。 这些解决方案是由许多软件开发人员在相当长的时间内通过试错获得的。 什么是 GOF&#xff08;四人帮&#xff0c;全拼 Gang of Four&#xff09…

Android 面试重点之Framework (Handler篇)

近期在网上看到不少Android 开发分享的面试经验&#xff0c;我发现基本每个面经中多多少少都有Framework 底层原理的影子。它也是Android 开发中最重要的一个部分&#xff0c;面试官一般会通过 Framework底层中的一些逻辑原理由浅入深进行提问&#xff0c;来评估应聘者的真实水…

[每周一更]-(第57期):用Docker、Docker-compose部署一个完整的前后端go+vue分离项目

文章目录 1.参考项目2.技能点3.GO的Dockerfile配置后端的结构如图Dockerfile先手动docker调试服务是否可以启动报错 4.Vue的Dockerfile配置前端的结构如图nginx_docker.confDockerfile构建 5.docker-compose 整合前后端docker-compose.yml错误记录&#xff08;1&#xff09;ip端…

Android复习(Android基础-四大组件)——Service与Activity通信

我们前面学会了启动和停止服务的方法&#xff0c;但是服务虽然是在活动里启动的&#xff0c;但是启动服务之后&#xff0c;活动与服务之间基本没什么关系了。正常情况&#xff0c;我们在Activity里调用startService()方法启动MyService这个服务&#xff0c;然后MyService的onCr…

Games101学习笔记 - MVP矩阵

MV矩阵&#xff08;模型视图变换&#xff09; 目的&#xff0c;把摄像机通过变换移动的世界坐标远点&#xff0c;并且朝向与Z轴的负方向相同。这个变换就是模型试图变换。 因为移动了相机&#xff0c;如果想保持正确的渲染的话&#xff0c;那么对应的物体需要要和相机保持相对…

day23-113. 路径总和ii

113. 路径总和ii 力扣题目链接(opens new window) 给定一个二叉树和一个目标和&#xff0c;找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 思路 利用…

机器学习(十八):Bagging和随机森林

全文共10000余字&#xff0c;预计阅读时间约30~40分钟 | 满满干货(附数据及代码)&#xff0c;建议收藏&#xff01; 本文目标&#xff1a;理解什么是集成学习&#xff0c;明确Bagging算法的过程&#xff0c;熟悉随机森林算法的原理及其在Sklearn中的各参数定义和使用方法 代码…

elasticsearch 查看所有集群设置_cluster/settings

curl --location http://127.0.0.1:9200/_cluster/settings?include_defaultstrue \ --header Authorization: Basic ssss样例数据 {"persistent": {"cluster": {"routing": {"allocation": {"node_concurrent_recoveries"…

【Spring】Spring中的设计模式

文章目录 责任链模式工厂模式适配器模式代理模式模版方法观察者模式构造器模式 责任链模式 Spring中的Aop的通知调用会使用责任链模式责任链模式介绍 角色&#xff1a;抽象处理者&#xff08;Handler&#xff09;具体处理者&#xff08;ConcreteHandler1&#xff09;客户类角…

14.3.4 【Linux】使用 LVM thin Volume 让 LVM 动态自动调整磁盘使用率

想像一个情况&#xff0c;你有个目录未来会使用到大约 5T 的容量&#xff0c;但是目前你的磁盘仅有 3T&#xff0c;问题是&#xff0c;接下来的两个月你的系统都还不会超过 3T 的容量&#xff0c; 不过你想要让用户知道&#xff0c;就是他最多有 5T 可以使用就是了&#xff01;…

Docker+rancher部署SkyWalking8.5并应用在springboot服务中

1.Skywalking介绍 Skywalking是一个国产的开源框架&#xff0c;2015年有吴晟个人开源&#xff0c;2017年加入Apache孵化器&#xff0c;国人开源的产品&#xff0c;主要开发人员来自于华为&#xff0c;2019年4月17日Apache董事会批准SkyWalking成为顶级项目&#xff0c;支持Jav…

Stable Diffusion - 俯视 (from below) 拍摄的人物图像 LoRA 与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132192139 图像来自 哥特风格 LoRA 俯视 LoRA&#xff0c;提升视觉冲击力&#xff0c;核心配置 <lora:view_from_below:0.6>,(from below,…