NestJS——多环境配置方案(dotenv、config、@nestjs/config、joi配置校验)

news2025/4/20 19:37:54

个人简介

👀个人主页: 前端杂货铺
🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

文章目录

    • 多环境配置方案
      • dotenv
      • config
    • @nestjs/config
    • 增加环境配置 .env 文件
    • 增加环境配置 .yml 文件
    • Joi 校验配置文件
    • 总结

多环境配置方案

测试项目的参考目录:

在这里插入图片描述

安装相关依赖:

npm i dotenv config js-yaml

创建 index.js 文件,用于后续测试。

dotenv

Dotenv

Dotenv 是一个零依赖模块,可将环境变量从 .env 文件加载到 process.env 中。

创建 .env 文件:

TOKEN_SECRET=your-long-random-secret

USERNAME=zahuopu
PASSWORD="mypassword-long-random-secret"

DATABASE_USERNAME=USERNAME
DATABASE_PASSWORD=PASSWORD

index.js 文件中添加如下代码:

require("dotenv").config();
console.log(process.env);

终端执行 node index.js 即可得到如下输出:

在这里插入图片描述

config

Node-config

Node-config 为我们的应用程序部署组织分层配置。它允许我们定义一组默认参数,并将其扩展到不同的部署环境(开发、质量保证、测试、生产等)。

创建 default.json 文件,默认文件。

{
    "token_secret": "long-secret",
    "db": {
        "host": "localhost",
        "port": 27017,
        "username": "zahuopu",
        "password": "example"
    }
}

创建 production.json 文件

{
    "db": {
        "host": "zahuopu.com",
        "port": 9000
    }
}

创建 development.json 文件

{
    "db": {
        "host": "qiandaun.com",
        "port": 3000
    }
}

index.js 文件中添加如下代码

const config = require("config");
const dbConfig = config.get("db");

console.log(dbConfig);

安装 cross-env 第三方库(cross-env是一个运行在 Node.js 环境中的工具包,它的主要作用是让我们可以在命令行中设置环境变量,而不必担心跨操作系统的兼容问题)

npm i cross env

修改 pageage.json 文件的如下内容

  "scripts": {
    "dev": "cross-env NODE_ENV=development node index.js",
    "prod": "cross-env NODE_ENV=production node index.js"
  },

在这里插入图片描述

在这里插入图片描述

此外,还支持 yaml 格式,即可以进行下面的写法:

使用 development.yaml 文件替换 .json 文件

db:
  host: "qianduan.com"
  port: 3000,

使用 production.yaml 文件替换 .json 文件

db:
  host: "zahuopu.com"
  port: 9000,

其效果是一样的。


@nestjs/config

@nestjs/config 是 NestJS 官方提供的一个模块,用于帮助开发者更轻松地管理加载应用程序的配置。它基于流行的 Node.js 库 dotenv,但提供了更强大、更 NestJS 风格的功能。

GitHub 提交记录

打开我们之前创建的 nestjs-demo 项目,安装 config

pnpm i --save @nestjs/config

app.module.ts 文件中,添加 Config 配置

import { Module } from "@nestjs/common";
import { UserModule } from "./user/user.module";
// 新加的内容
import { ConfigModule } from "@nestjs/config";

@Module({
  imports: [
  	// 新加的内容
    ConfigModule.forRoot({
      isGlobal: true, // 将配置模块声明为全局模块,所有其他模块均可直接注入 ConfigService
    }),
    UserModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

src 目录下创建 enum 文件夹,并在新创建的文件夹中创建 config.const.ts 文件,在此文件中我们定义一些枚举值,用于配置

export enum ConfigEnum {
  DB = "DB",
  DB_HOST = "DB_HOST",
}

user.controller.ts 中进行测试

import { Controller, Get, Post } from "@nestjs/common";
import { UserService } from "./user.service";
// 新增的引入
import { ConfigService } from "@nestjs/config";
import { ConfigEnum } from "src/enum/config.const";

@Controller("user")
export class UserController {
  constructor(
    private userService: UserService,
    private configService: ConfigService
  ) {}
  @Get()
  getUsers(): any {
  	// 新增的测试内容 ---------------------------------
    const db = this.configService.get(ConfigEnum.DB);
    const host = this.configService.get(ConfigEnum.DB_HOST);
    console.log("db", db);
    console.log("host", host);
    // ----------------------------------------------

    return this.userService.getUsers();
  }
}

启动项目后,访问 http://localhost:3000/api/user 网址,即可在终端得到如下输出。

在这里插入图片描述


增加环境配置 .env 文件

GitHub提交记录

在这里插入图片描述

安装 cross-env、dotenv。
cross-env

作用:
跨平台环境变量设置
cross-env 是一个解决不同操作系统(Windows/macOS/Linux)环境变量设置语法差异的工具。它允许你在 package.json 的脚本中统一设置环境变量,无需关心底层操作系统的差异。

dotenv

作用:
从 .env 文件加载环境变量
dotenv 是一个零依赖的库,用于将 .env 文件中的键值对注入到 Node.js 的 process.env 中,使得应用可以方便地读取配置。
为什么需要它?
分离敏感配置:避免将数据库密码、API 密钥等硬编码在代码中。

pnpm i -D cross-env
pnpm i dotenv

修改 package.json 文件

"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:prod": "cross-env NODE_ENV=production node dist/main",

创建 .env.development 文件,进行开发环境下 DB 及 DB_HOST 的配置。

DB=mysql-dev
DB_HOST=127.0.0.1

创建 .env.production 文件,进行生产环境下 DB 及 DB_HOST 的配置。

DB=mysql-prod
DB_HOST=127.0.0.1

修改 .env 文件内容

# 公共配置文件
DB=mysql
DB_HOST=127.0.0.1

# 新增内容
DB_URL=https://zahuopu.blog.csdn.net/

修改 app.module.ts 文件

import { Module } from "@nestjs/common";
import { UserModule } from "./user/user.module";
import { ConfigModule } from "@nestjs/config";
// 导入 dotenv 库,用于解析 .env 文件
import * as dotenv from "dotenv";

/**
 * 动态生成环境变量文件路径:
 * - 如果系统环境变量 `NODE_ENV` 存在(如 production、development、test),则加载对应的 `.env.[NODE_ENV]` 文件
 * - 默认使用 `.env.development` 文件
 */
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // 将配置模块声明为全局模块,所有其他模块均可直接注入 ConfigService
      envFilePath, // 指定环境变量文件路径(根据 NODE_ENV 动态加载)
      // 自定义配置加载器:显式加载默认的 .env 文件(作为兜底配置)
      // 注:如果同时存在 envFilePath 和此配置,envFilePath 的变量会覆盖 .env 的重复键
      load: [() => dotenv.config({ path: ".env" })],
    }),
    UserModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

user.controller.ts 文件中做验证

import { Controller, Get, Post } from "@nestjs/common";
import { UserService } from "./user.service";
import { ConfigService } from "@nestjs/config";
import { ConfigEnum } from "src/enum/config.const";

@Controller("user")
export class UserController {
  constructor(
    private userService: UserService,
    private configService: ConfigService
  ) {}
  @Get()
  getUsers(): any {
    const db = this.configService.get(ConfigEnum.DB);
    const host = this.configService.get(ConfigEnum.DB_HOST);
    console.log("db", db);
    console.log("host", host);

	// 新添加的内容-------------------------
    const url = this.configService.get("DB_URL");
    console.log("url", url);
    //------------------------------------

    return this.userService.getUsers();
  }}
}

在这里插入图片描述

在这里插入图片描述


增加环境配置 .yml 文件

GitHub 提交记录

在这里插入图片描述

安装 js-yaml、@types/js-yaml、lodash

js-yaml

作用:
YAML 解析与序列化
js-yaml 是一个 JavaScript 库,用于解析 YAML(一种人类友好的数据序列化格式)文件或字符串,并将其转换为 JavaScript 对象,同时也支持将 JavaScript 对象序列化为 YAML 格式。
典型使用场景:
读取配置文件(如 .yaml 或 .yml 文件)。
在前后端通信中处理 YAML 格式的数据(虽然 JSON 更常见,但某些场景如 Kubernetes 配置依赖 YAML)。

@types/js-yaml

作用:
TypeScript 类型定义
@types/js-yaml 是 js-yaml 的 TypeScript 类型声明文件(通过 DefinitelyTyped 维护),为 js-yaml 提供类型支持,使得在 TypeScript 项目中调用 js-yaml 时可以获得代码补全和类型检查。
为什么需要它?
如果你在 TypeScript 项目中使用 js-yaml,直接安装 js-yaml 会导致类型错误(因为它是纯 JavaScript 库)。
通过 @types/js-yaml,TypeScript 能识别 yaml.load()、yaml.dump() 等方法的参数和返回值类型。

lodash

lodash 是一个提供高效、模块化的工具函数库,用于简化常见的数据操作(如数组、对象、字符串处理等)。

pnpm i js-yaml
pnpm i -D @types/js-yaml
pnpm i lodash

创建 config 文件夹,在此文件夹中创建三个文件。

config.yml 文件中进行 公有配置

db:
  mysql1:
    host: 127.0.0.1
    name: test-name
    port: 3306

  mysql2:
    host: 127.0.0.1
    name: test-name1
    port: 3306

config.development.yml 文件中进行 开发环境 配置

db:
  mysql1:
    name: mysql-dev
  mysql2:
    name: mysql-dev1

config.production.yml 文件中进行 生产环境 配置

db:
  mysql1:
    name: mysql-prod
  mysql2:
    name: mysql-prod1

创建 configuration.ts 配置文件,添加如下代码

import { readFileSync } from "fs"; // 用于同步读取文件内容
import * as yaml from "js-yaml"; // 用于解析 YAML 文件
import { join } from "path"; // 用于处理文件路径
import * as _ from "lodash"; // 用于对象的深度合并等操作

// 定义通用配置文件的文件名
const YAML_COMMON_CONFIG_FILENAME = "config.yml";

// 构建通用配置文件的路径
const filePath = join(__dirname, "../config", YAML_COMMON_CONFIG_FILENAME);

// 根据当前环境(NODE_ENV)构建环境配置文件的路径,默认为 "development"
const envPath = join(
  __dirname,
  "../config",
  `config.${process.env.NODE_ENV || "development"}.yml`
);

// 加载通用配置文件内容
const commonConfig = yaml.load(readFileSync(filePath, "utf8"));

// 加载环境配置文件内容
const envConfig = yaml.load(readFileSync(envPath, "utf8"));

// 导出一个函数,返回合并后的配置对象
export default () => {
  // 使用 lodash 的 merge 方法,将通用配置和环境配置深度合并
  return _.merge(commonConfig, envConfig);
};

修改 app.module.ts,更改配置

import { Module } from "@nestjs/common";
import { UserModule } from "./user/user.module";
import { ConfigModule } from "@nestjs/config";
// 新增内容--------------------------------
import Configuration from "./configuration";
// ---------------------------------------

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // 将配置模块声明为全局模块,所有其他模块均可直接注入 ConfigService
      // 修改的内容-----------------
      load: [Configuration],
      // -------------------------
    }),
    UserModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

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 data = this.configService.get("db");
    console.log("data", data);
    // ---------------------------------------

    return this.userService.getUsers();
  }
}

在这里插入图片描述

在这里插入图片描述


Joi 校验配置文件

Joi模式验证器官网

我们可以使用 Joi 来校验我们的配置文件

安装 joi

pnpm install --save joi

GitHub 提交记录

我们基于 dotenv 的配置方式在 app.module.ts 文件中使用它

import { Module } from "@nestjs/common";
import { UserModule } from "./user/user.module";
import { ConfigModule } from "@nestjs/config";
import * as dotenv from "dotenv"; // 导入 dotenv 库,用于解析 .env 文件
import * as Joi from "joi"; // 用于验证环境变量的库

/**
 * 动态生成环境变量文件路径:
 * - 如果系统环境变量 `NODE_ENV` 存在(如 production、development、test),则加载对应的 `.env.[NODE_ENV]` 文件
 * - 默认使用 `.env.development` 文件
 */
const envFilePath = `.env.${process.env.NODE_ENV || "development"}`;

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // 将配置模块声明为全局模块,所有其他模块均可直接注入 ConfigService
      envFilePath, // 指定环境变量文件路径(根据 NODE_ENV 动态加载)
      /**
       * 自定义配置加载器:
       * - 显式加载默认的 `.env` 文件,作为兜底配置
       * - 如果 `envFilePath` 和 `.env` 文件中存在相同的变量,`envFilePath` 的变量会覆盖 `.env` 中的值
       */
      load: [() => dotenv.config({ path: ".env" })],
      /**
       * 使用 Joi 验证环境变量:
       * - 定义环境变量的结构和默认值
       * - 确保环境变量的值符合预期(如类型、范围等)
       */
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid("development", "production", "test") // 限制 NODE_ENV 的合法值
          .default("development"), // 默认值为 "development"
        DB_PORT: Joi.number().default(3306), // 数据库端口,默认值为 3306
        DB_URL: Joi.string().domain(), // 数据库 URL,必须是合法的域名
        DB_HOST: Joi.string().ip(), // 数据库主机地址,必须是合法的 IP 地址
      }),
    }),
    UserModule, // 导入用户模块
  ],
  controllers: [], // 控制器(当前为空)
  providers: [], // 服务提供者(当前为空)
})
export class AppModule {}

下面我们进行验证一下,如果我们在 .env.development 文件中把 DB_PORT=xxx

DB=mysql-dev
DB_HOST=127.0.0.1
DB_PORT=xxx

DB_URL=www.baidu.com

那么启动项目时会发现:

在这里插入图片描述


总结

本篇文章,我们学习了多环境配置方案,包括:dotenv、config及在 nestjs 项目中的使用等。此外,我们还认识了配置校验工具joi,保障配置符合规范等。

好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!


参考资料:

  1. DeepSeek
  2. NestJS 从入门到实战

在这里插入图片描述


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

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

相关文章

MongoDB导出和导入数据

安装mongodump工具 参考文章mongodump工具安装及使用详解_mongodump安装-CSDN博客 MongoDB导入导出和备份的命令工具从4.4版本开始不再自动跟随数据库一起安装,而是需要自己手动安装。 官方网站下载链接:Download MongoDB Command Line Database Tools …

Serving入门

ServingHelloWorld Serverless 一个核心思想就是按需分配,那么 Knative 是如何实现按需分配的呢?另外在前面已经了解到 Knative Serving 在没有流量的时候是可以把Pod 缩容到零的。接下来就通过一些例子体验一下 Knative 缩容到零和按需自动扩缩容的能力…

【HDFS入门】HDFS数据冗余与容错机制解析:如何保障大数据高可靠存储?

目录 1 HDFS冗余机制设计哲学 1.1 多副本存储策略的工程权衡 1.2 机架感知的智能拓扑算法 2 容错机制实现原理 2.1 故障检测的三重保障 2.2 数据恢复的智能调度 3 关键场景容错分析 3.1 数据中心级故障应对 3.2 数据损坏的校验机制 4 进阶优化方案 4.1 纠删码技术实…

UE学习记录part19

231 insect: insect enemy type 创建dead动画资源 往insect head上添加socket 创建攻击root motion动画。motion warping需要与root motion合作使用 为buff_blue创建物理资产 设置simulate physic使sinsect死亡后能落到地板上而不是漂浮在空中,要将die函数设置为 -…

运行后allure报告没有自动更新(已解决)

pycharm直接运行run.py文件, allure生成的报告都没有更新,需要手动删除旧报告后再次运行才可以 pytest.ini [pytest]testpaths testcases/ addopts --alluredir ./report/result --clean-alluredir run.py主要代码 if __name__ "__main__&qu…

微信小程序 时间戳与日期格式的转换

1. 微信小程序 时间戳与日期格式的转换 微信小程序中的时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。例如现在北京时间2015-12-31 17:00:00的时间戳是1451552400,就是指从北京时间1970-01-01 08:00:00到…

【深度学习—李宏毅教程笔记】Transformer

目录 一、序列到序列(Seq2Seq)模型 1、Seq2Seq基本原理 2、Seq2Seq模型的应用 3、Seq2Seq模型还能做什么? 二、Encoder 三、Decoder 1、Decoder 的输入与输出 2、Decoder 的结构 3、Non-autoregressive Decoder 四、Encoder 和 De…

【人工智能学习-01-01】20250419《数字图像处理》复习材料的word合并PDF,添加页码

前情提要 20250419今天是上师大继续教育人工智能专升本第一学期的第一次线下课。 三位老师把视频课的内容提炼重点再面授。(我先看了一遍视频,但是算法和图像都看不懂,后来就直接挂分刷满时间,不看了) 今天是面对面授…

使用 Docker 安装 Elastic Stack 并重置本地密码

Elastic Stack(也被称为 ELK Stack)是一个非常强大的工具套件,用于实时搜索、分析和可视化大量数据。Elastic Stack 包括 Elasticsearch、Logstash、Kibana 等组件。本文将展示如何使用 Docker 安装 Elasticsearch 并重置本地用户密码。 ###…

利用 Deepseek 和 Mermaid 画流程图

提示词 你是一个产品经理,请绘制一个报名比赛的流程图,要求生成符合Mermaid语法的代码,具体要求如下: 1.注册账号 2.填写报名信息 3.参加比赛 4.查看比赛结果 生成的结果 flowchart TDA([开始]) --> B[注册账号]B --> C{账…

学习笔记: Mach-O 文件

“结构决定性质,性质决定用途”。如果不了解结构,是很难真正理解的。 通过一个示例的可执行文件了解Mach-O文件的结构 Mach-O基本结构 Header: :文件类型、目标架构类型等Load Commands:描述文件在虚拟内存中的逻辑结构、布局Data: 在Load commands中…

个人自用-导入安装Hexo

因为本人原来就有备份好的资料,所以重新安装起来会很方便,这个教程也只适合我自己用 但是所有的命令行都要在Git的命令行里面使用(因为我就是这样操作的) 1 安装Git Git的官网 Git git --version 这个是查看Git的版本 git --…

《AI大模型应知应会100篇》第26篇:Chain-of-Thought:引导大模型进行步骤推理

第26篇:Chain-of-Thought:引导大模型进行步骤推理 摘要 在自然语言处理(NLP)和人工智能领域,如何让大模型像人类一样进行逐步推理是一个核心挑战。Chain-of-Thought (思维链) 技术的出现为这一问题提供了强有力的解决…

STM32单片机入门学习——第43节: [12-3] 读写备份寄存器实时时钟

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.04.19 STM32开发板学习——第43节: [12-3] 读写备份寄存器&实时时钟 前言开发板说明…

零基础上手Python数据分析 (18):Matplotlib 基础绘图 - 让数据“开口说话”

写在前面 —— 告别枯燥数字,拥抱可视化力量,掌握 Matplotlib 绘图基础 欢迎来到 “高效数据分析实战指南:Python零基础入门” 专栏! 经过前面 Pandas 模块的学习和实战演练,我们已经掌握了使用 Python 和 Pandas 进行数据处理、清洗、整合、分析的核心技能。 我们能够从…

【网络原理】UDP协议

目录 一. UDP 报文格式 (1)端口号 (2)UDP长度 (3)校验和 UDP协议属于传输层协议,由操作系统内核内置 一. UDP 报文格式 UDP数据报:无连接,不可靠传输,面…

HCIP OSPF综合实验

1.网络拓扑图 实验要求: 2.需求分析 IP规划: 对每个路由器配置ospf并用172.16.0.0/16网段进行划分,项目中一共有area0 - area4五个ospf区域加一个rip网段,所以我们在172.16.0.0/16选出6个网段 ISP 对r5只能配ip可以把他看成外…

实现批量图片文字识别(python+flask+EasyOCR)

话不多说,向上效果图 1)先说框架版本 为什么要先说框架版本呢,因为我在各种版本中尝试了两天,总算确定了如下版本适合我,至于其他的版本,各位自己去尝试 python 3.9.7 EasyOCR 1.7.2 flask 3.0.3 2)执行操作效果图 2.1)多选文件 2.2)图片预览 2.3)提取选中文件 2.4)提取所有文…

【java实现+4种变体完整例子】排序算法中【堆排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是堆排序的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格: 一、堆排序基础实现 原理 基于二叉堆结构(最大堆),通过以下步骤实现排序: 构建最大堆:将…

WhatTheDuck:一个基于浏览器的CSV查询工具

今天给大家介绍一个不错的小工具:WhatTheDuck。它是一个免费开源的 Web 应用程序,允许用户上传 CSV 文件并针对其内容执行 SQL 查询分析。 WhatTheDuck 支持 SQL 代码自动完成以及语法高亮。 WhatTheDuck 将上传的数据存储为 DuckDB 内存表,继…