这篇是Nest微服务训练营基础篇一小节,训练营大概会有100多篇关于Nest实操的文字,本小节讲述开发过程中环境变量的区分,更多精彩文章关注我,

一、简单的使用​​.env​​文件来实现配置文件

  • 1、安装依赖包

npm install dotenv
npm install @types/dotenv -D

  • 2、根目录下创建一个​​.env​​​的文件,如果是线上项目将​​.env​​​加入到​​.gitignore​​中,如果是自己学习阶段无所谓
  • 3、在​​.env​​文件中写入端口号及项目前缀

PREFIX=api/v1
PORT=4000

  • 4、在main.ts中使用

import 'dotenv/config'; // 这行是关键代码
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

export const IS_DEV = process.env.NODE_ENV !== 'production';
const PORT = process.env.PORT || 8080;
const PREFIX = process.env.PREFIX || '/';

async function bootstrap() {
const logger: Logger = new Logger('main.ts');
const app = await NestFactory.create(AppModule, {
// 开启日志级别打印
logger: IS_DEV ? ['log', 'debug', 'error', 'warn'] : ['error', 'warn'],
});
await app.listen(PORT, () => {
logger.log(`服务已经启动,接口请访问:http://wwww.localhost:${PORT}/${PREFIX}`);
});
}
bootstrap();

  • 5、这种方式使用简单,只要安装两个依赖包就可以,但是不足之处在于不能区分开发环境和生产环境的配置,都统一写在​​.env​​​文件中,每次要使用的时候还要​​process.env.xx​​的方式来使用,下面会介绍如何区分开发环境和生产环境使用不同的配置文件,方便环境中变量的管理

二、使用​​config​​的依赖包来方便获取配置文件中的配置

npm install @nestjs/config

  • 2、在​​app.module.ts​​中使用

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env'],
}),
],
controllers: [AppController],
providers: [AppService, Logger],
})
export class AppModule {}

  • 3、在需要获取配置的地方使用​​ConfigService​​​提供一个​​get​​方法来获取

console.log(this.configService.get('PORT'), '当前的端口');

  • 4、说明下如果使用了​​@nestjs/config​​​这个包,在​​main.ts​​​文件首部可以不用引入​​import 'dotenv/config'​

三、使用​​.env​​的方式来区分环境

  • 1、在项目根目录下分别创建​​.env​​​、​​.env.dev​​​、​​.env.prod​​​文件并且在​​ConfigModule​​中加载

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: ['.env.dev', '.env', '.env.prod'],
}),
],
controllers: [AppController],
providers: [AppService, Logger],
})
export class AppModule {}

  • 2、根据官网上的介绍是前面的优先级比后面的优先级高,简单的理解就是在获取的时候会先查找​​envFilePath​​​数组的第一项,里面有就直接返回当前的,如果没有就会查找第二个,根据这个原理我们可以重新来编排下​​envFilePath​​数组项
  • 3、安装依赖包来配置设置当前环境,上面使用​​process.env.NODE_ENV​​已经不能判断当前是什么环境

npm install cross-env

  • 4、手动配置启动环境的配置,修改​​package.json​​文件启动命令

...
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "cross-env RUNNING_ENV=dev nest start",
"start:dev": "cross-env RUNNING_ENV=dev nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "cross-env RUNNING_ENV=prod node dist/main",
}
...

  • 5、重新定义获取当前环境的变量,注意不能定义在​​main.ts​​​中,必须定义在​​app.module.ts​​文件中

export const IS_DEV = process.env.RUNNING_ENV !== 'prod';

  • 6、根据环境来切换配置

import { Logger, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
let envFilePath = ['.env'];
export const IS_DEV = process.env.RUNNING_ENV !== 'prod';

if (IS_DEV) {
envFilePath.unshift('.env.dev');
} else {
envFilePath.unshift('.env.prod');
}
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath,
}),
],
controllers: [AppController],
providers: [AppService, Logger],
})
export class AppModule {}
import { AppModule, IS_DEV } from './app.module';

const PORT = process.env.PORT || 8080;
const PREFIX = process.env.PREFIX || '/';

console.log(`Port: ${PORT}`, IS_DEV);

  • 7、尝试从​​.env.dev​​​文件中删除​​PORT​​​的时候控制台会打印出​​.env​​​的端口,如果加上会打印出​​.env.dev​​的端口
  • 8、关于​​.env​​​、​​.env.dev​​​、​​.env.prod​​几个文件说明
  • ​.env​​文件存放一些通用的配置,在开发环境和生产环境都保持一样的
  • ​.env.dev​​文件存放开发环境的配置
  • ​.env.prod​​文件存放生产部署需要的配置
  • 9、关于使用​​.env​​​来配置不同环境的代码参考,​​代码地址​

四、使用​​yml​​文件来做配置文件

npm install yaml

  • 3、在根目录下创建​​application.dev.yml​​​和​​application.prod.yml​​​两个文件来区分配置开发环境和生产环境,并且添加值​​.gitignore​​文件中
  • 4、创建一个文件用来读取配置​​utils/config.ts​

import { parse } from 'yaml';
import * as path from 'path';
import * as fs from 'fs';

// 获取项目运行环境
export const getEnv = () => {
return process.env.RUNNING_ENV;
};

export const IS_DEV = getEnv() === 'dev';
// 读取项目配置
export const getConfig = () => {
const environment = getEnv();
console.log(environment, '当前运行的环境');
const yamlPath = path.join(process.cwd(), `./application.${environment}.yml`);
const file = fs.readFileSync(yamlPath, 'utf8');
const config = parse(file);
return config;
};

  • 5、修改​​app.module.ts​​文件的配置

import { Logger, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { getConfig } from './utils';

@Module({
imports: [
ConfigModule.forRoot({
ignoreEnvFile: false, // 忽视默认读取.env的文件配置
isGlobal: true, // 全局注入
load: [getConfig], // 加载配置文件
}),
],
controllers: [AppController],
providers: [AppService, Logger],
})
export class AppModule {}

  • 6、修改​​main.ts​​​文件,之前直接从​​process.env.​​的方式获取不到配置项目了,要改为方法的调用方式

import { getConfig, IS_DEV } from './utils';

const config = getConfig();
const PORT = config.PORT || 8080;
const PREFIX = config.PREFIX || '/';
... 省去100行代码

  • 7、在别的地方要获取配置文件和之前一样的使用​​this.configService.get('PORT')​​的方式来获取
  • 8、本小节代码见,​​代码地址​