Skip to content

配置管理

在模块中,手写过配置项模块,但是为了加快开发的速度,提高开发的效率,通过使用安装ConfigModule包来进行配置项的管理

安装依赖

在开发NestJs后端的时候,一般需要使用到以下的包:

安装命令:pnpm add -D prisma-binding @prisma/client mockjs @nestjs/config class-validator class-transformer argon2 @nestjs/passport passport passport-local @nestjs/jwt passport-jwt lodash multer dayjs express

或者:npm install -D prisma-binding @prisma/client mockjs @nestjs/config class-validator class-transformer argon2 @nestjs/passport passport passport-local @nestjs/jwt passport-jwt lodash multer dayjs express

命令中的一系列开发依赖项:

  • prisma-bindingPrisma BindingPrisma 的一个JavaScript客户端库,它提供了一组用于构建 GraphQL 解析器的工具。可以轻松地将Prisma Client集成到GraphQL服务器中

  • @prisma/clientPrisma Client Prisma 自动生成的用于与数据库进行交互的 JavaScript/TypeScript 客户端库。它提供了一组 API 来执行 CRUD 操作以及其他与数据库相关的操作

  • mockjsMock.js 是一个用于生成随机数据的 JavaScript 库,它可以帮助你模拟开发和测试环境中的数据

  • @nestjs/configNestJS 的配置模块,用于管理应用程序的配置信息。可以帮助我们从不同的源(如环境变量、配置文件等)加载配置,并在整个应用程序中使用

  • class-validator:于验证类和对象的 TypeScript/JavaScript 库,帮助我们轻松地定义和应用验证规则,以确保数据的有效性和完整性

  • class-transformer:用于转换类和对象的 TypeScript/JavaScript 库,可以帮助我们轻松地在不同的数据结构之间进行转换和映射

  • argon2:一种密码哈希算法,密码安全性更高的替代方案,可以帮助你安全地存储用户密码

  • @nestjs/passportNestJS Passport模块,用于在 NestJS 应用程序中实现身份验证和授权功能

  • passport:是Node.js中一个流行的身份验证中间件,提供了一组易于使用的策略来实现身份验证功能

  • passport-localPassport 中用于处理本地身份验证的策略,它允许用户使用用户名和密码进行身份验证

  • @nestjs/jwtNestJSJWT 模块,用于在 NestJS 应用程序中实现 JWTJSON Web Token)身份验证和授权功能

  • passport-jwtPassport 中用于处理 JWT 身份验证的策略,它允许我们使用 JWT 来实现无状态的身份验证

  • lodashLodashJavaScript中一个实用工具库,提供了许多常用的工具函数,可以帮助你简化 JavaScript 编程

  • multerMulter 是一个 Node.js 中用于处理文件上传的中间件,它可以帮助我们处理表单数据中的文件上传功能

  • dayjsDay.js 是一个轻量级的JavaScript日期处理库,它提供了简单易用的 API 来处理日期和时间

@nestjs/config这个包是用来管理我们配置项的,使用方式和我们手写的配置项模块类似


加载配置项

根配置文件.env中配置项加载

我们先要到app.module.ts文件中导入并定义这个模块:

ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';

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

在使用的时候,我们去我们创建的.env.env文件在根目录中创建)配置文件中读取我们添加的配置项内容:

ts
BLOG_NAME = JBLOG

在本地开发的时候,会有一些其他的配置项,如阿里云的密钥等,这些密钥一般是隐私的,我们不能将其提交到代码仓库的,所以.env这个文件一般要在git的忽略文件中进行忽略,如果代码部署到服务器上的时候,我们在拉取代码后,将.env这个文件复制过去即可

ConfigModule模块会自动的读取这个配置文件

在控制器文件app.controller.ts中,将读取配置项服务引入:

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 readonly config: ConfigService) {}

  @Get()
  getHello() {
    return this.config.get('BLOG_NAME');
  }
}

在网页地址中输入:localhost:3000,可以看到读取的配置项内容:JBLOG

对于配置项操作,一般简单的项目,我们将配置项内容放在.env文件中即可

其他配置文件的配置项加载

我们可以在src文件夹中自定义创建一些模块的配置文件,比如,为根模块创建一个配置文件:app.config.ts,具体内容为:

ts
export default () => ({
    app: {
        name: 'JBLOG'
    }
})

ConfigModule模块是不认这个配置文件的,我们需要在app.module.ts文件中为ConfigModule模块添加一个选项,将这个配置文件加载过来:

ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { appConfig } from './app.config'

@Module({
  imports: [ConfigModule.forRoot({
      isGlobal: true,
      load: [appConfig]
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

加载之后,自定义的配置文件就会和.env根配置文件进行合并,可以一起被ConfigModule模块读取到

在控制器文件app.controller.ts中,将读取配置项服务引入:

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 readonly config: ConfigService) {}

  @Get()
  getHello() {
    return this.config.get('app.name');
  }
}

在网页地址中输入:localhost:3000,可以看到读取的配置项内容:JBLOG


process.env环境变量

process.env可以读取到当前的环境变量,包括当前的工作目录、操作系统等等,其中项目中的.env配置也会加载到环境变量中

对于.env文件的内容:

ts
BLOG_NAME = JBLOG

我们也可以使用process.env.BLOG_NAME的方式进行配置内容的读取,不单单只是通过ConfigService服务进行配置项内容的读取

根据当前环境读取不同配置项内容

.env文件,加上NODE_ENV项进行区分不同的开发环境:

ts
NODE_ENV = development
BLOG_NAME = JBLOG

app.config.ts文件中进行当前环境的判断,具体内容为:

ts
export default () => ({
    app: {
        name: 'JBLOG',
        isDev: process.env.NODE_ENV === 'development'
    }
})

app.module.ts文件中为ConfigModule模块添加一个选项,将这个配置文件加载过来:

ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { appConfig } from './app.config'

@Module({
  imports: [ConfigModule.forRoot({
      isGlobal: true,
      load: [appConfig]
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

在控制器文件app.controller.ts中,将读取配置项服务引入:

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 readonly config: ConfigService) {}

  @Get()
  getHello() {
      if (this.config.get('app.isDev')){
          return this.config.get('app.name');
      }
  }
}

当前为开发环境的时候,进行对应内容的打印

在网页地址中输入:localhost:3000,可以看到读取的配置项内容:JBLOG

这样对于不同的开发环境选择不同的策略,如对于生产环境,是不是需要进行运行日志的打印


多配置文件定义

多配置文件就是我们采用多个文件来定义不同模块的配置项,最后将其都放到一个config文件夹中进行统一管理,一般在这个文件夹中写一个入口文件index.ts,进行所有配置项的统一导出管理

config文件夹下编写两个模块的配置项文件,如:app.config.tsdb.config.ts

ts
export default () => ({
    app: {
        name: 'JBLOG'
    }
})
ts
export default () => ({
    database: {
        host: 'localhost'
    }
})

编写入口文件index.ts

ts
import appConfig from './app.config';
import dbConfig from './db.config';

export default [appConfig, dbConfig];

在根模块中,配置模块调用加载,使用ConfigModule模块可以找到这个自定义的配置项内容:

ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { config } from './config'

@Module({
  imports: [ConfigModule.forRoot({
      isGlobal: true,
      load: [...config]    // 是一个数组,需要进行展开
  })],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

但是这种情况在调用的时候this.config.get('app.name'),输入app,系统是不会给出类型提示的

命名空间配置项

为了解决上述没有代码提示的情况,我们需要进行基于命名空间的配置,在配置文件中进行修改,以db.config.ts修改为例:

ts
import { registerAs } from '@nestjs/config';

export default registerAs('database', () => ({
	host: 'localhost'
}))

在控制器服务调用的app.controller.ts文件中进行依赖的注入和类型的添加:

ts
import { Controller, Get } from '@nestjs/common';
import { ConfigService, ConfigType } from '@nestjs/config';
import { AppService } from './app.service';
import dbConfig from './config/db.config'

@Controller()
export class AppController {
  constructor(private readonly appService: AppService,
              private readonly config: ConfigService
              // 将配置内容当作模块文件中providers的对象内容进行使用,调用时需进行注入
              @Inject(dbConfig.KEY) private database: ConfigType<typeof dbConfig>) {}

  @Get()
  getHello() {
      return this.database.host    // 这时再输入database后,就会有代码提示,告知对象下的所有KEY
  }
}

@nestjs/config包中为我们提供了类型提示工具:ConfigType,将所需要的配置内容typeof dbConfig传入即可,后续在使用的时候,就会有代码提示

Released under the MIT License.