个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨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,保障配置符合规范等。
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- DeepSeek
- NestJS 从入门到实战