快速入门nest.js(7/10)--应用配置

简介: 然后,你就可以像下面的方式使用对应的变量值了,注意这里所有的变量值都是字符串,而port要求的是数字,所以我们还需要进行一个转换。

准备


// npm i @nestjs/config

然后在导入:

// app.module
import { ConfigModule } from '@nestjs/config';
@Module({
  imports: [
    // forRoot 将从默认位置(根目录)加载和解析我们的.env文件
    // ConfigModule还将.env文件中的键/值对与分配给`process.env`的环境变量合并
    ConfigModule.forRoot(),
      // ...


然后在根目录下创建.env文件

DATABASE_USER=postgres
DATABASE_PASSWORD=pass123
DATABASE_NAME=postgres
DATABASE_PORT=5432
DATABASE_HOST=localhost

注意,你应该在.gitignore文件下添加*.env

使用


然后,你就可以像下面的方式使用对应的变量值了,注意这里所有的变量值都是字符串,而port要求的是数字,所以我们还需要进行一个转换。

@Module({
  imports: [
    // forRoot 将从默认位置(根目录)加载和解析我们的.env文件
    // ConfigModule还将.env文件中的键/值对与分配给`process.env`的环境变量合并
    ConfigModule.forRoot(),
    CoffeesModule,
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: process.env.DATABASE_HOST,
      port: +process.env.DATABASE_PORT,  // 这里做了隐式转换
      username: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE_NAME,
      autoLoadEntities: true,
      synchronize: true,
    }),
    CoffeeRatingModule,
    DatabaseModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})

切换路径


下面这种方式就会从根目录的.environment中找。

ConfigModule.forRoot({envFilePath: '.environment'}),


禁用


有时候,需要禁用,如下:

ConfigModule.forRoot({ignoreEnvFile: true}),


验证配置


配置未通过验证,抛出异常是一个最佳做法。

// npm i @hapi/joi
// npm i --save-dev @types/hapi__joi  // 相关的类型声明文件


定义一个Joi验证模式

import * as Joi from '@hapi/joi';  // 确保这里导入了所有
ConfigModule.forRoot({
    validationSchema:Joi.object({
        DATABASE_HOST: Joi.required(),  // 默认情况下,所有键都是可选的,这里设置为必选的
        DATABASE_PORT: Joi.number().default(5432),
    })
}),


ConfigService



我们在应用程序中设置的ConfigModule带有一个名为ConfigService的有用服务,其中有一个get方法来读取我们所有已解析的配置变量。

首先导入

// coffees.module
@Module({
  imports: [/* ... */, ConfigModule],
    // ...


然后就可以导入ConfigService注入到constructor

@Injectable()
export class CoffeesService {
  constructor(
  //...
    private readonly configService: ConfigService,
  ) {  // 这里的string只是编译器上的string,即使我们指定为number,也不会进行任何的类型转换
    const databaseHost = this.configService.get<string>('DATABASE_HOST')
    console.log(databaseHost);
  }


get还有第二个参数作为默认值进行使用:

this.configService.get<string>('DATABASE_HOST', 'localhost')


分组配置


创建文件config/app.config.ts

export default () =>({
  environment: process.env.NODE_ENV || 'development',
  database: {
    host: process.env.DATABASE_HOST,
    port:parseInt(process.env.DATABASE_PORT, 10) || 5432
  }
})

    


然后在app.module中使用它

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [appConfig],
    }),
      // ...


同样,这里我们也可以使用上一部分提到的ConfigService.get()使用其中的配置,因为该方法不仅允许你通过键检索环境变量,还可以遍历我们自定义文件中创建的嵌套自定义配置对象。

// coffees.service
// ...
    private readonly configService: ConfigService,
  ) {
    const databaseHost = this.configService.get('database.host','localhost')  // 这里没有<string>了
    console.log(databaseHost);
  }


注意这里是使用的database.host获取属性,因为在config中我们是这样定义的

  database: {
    host: process.env.DATABASE_HOST,
    port:parseInt(process.env.DATABASE_PORT, 10) || 5432
  }


这对于大型复杂应用来说,可能会很快变得不可维护,因为这种方法没有类型推断,'database.host'这是个字符串,我们不断的输入字符串,根本不知道对应位置是否有相应的属性。


配置的NameSpace


/coffees/文件夹中创建一个新的/config/目录,并在其中创建coffees.config.ts文件

import { registerAs } from "@nestjs/config";
// registerAs在对应的key上注册了一个命名空间配置对象
export default registerAs('coffees', ()=>({
  foo: 'bar',
}))

    


然后在coffees.module中使用.forFeature()导入:


    
@Module({
  imports: [
    TypeOrmModule.forFeature([Coffee, Flavor, Event]),
    ConfigModule.forFeature(coffeesConfig),
  ], // 部分注册,在靠近其域的位置注册它们,而不是将所有这些文件加载到根目录
 // 并且,我们之前也使用了ConfigModule.forRoot处理了根模块中的配置文件


在对应的service中使用:

@Injectable()
export class CoffeesService {
  constructor(
// ...
    private readonly configService: ConfigService,
  ) {
    const coffeesConfig = this.configService.get('coffees')
    console.log(coffeesConfig);
  }


控制台: { foo: 'bar' }
const coffeesConfig = this.configService.get('coffees.foo')  // log: bar


为了避免这种在字符串中使用.运算符,从而可能造成一些小错误,所以我们通常是直接注入整个命名空间配置对象,每个命名空间配置都暴露了一个key属性

//...    
@Inject(coffeesConfig.KEY)
    private readonly coffeesConfiguration: ConfigType<typeof coffeesConfig>,
  ) {
    console.log(coffeesConfiguration.foo);  // 这里就会有检查和提示
  }

异步配置


@Module({
  imports: [
    ConfigModule.forRoot({   // 1
      load: [appConfig],
    }),
    CoffeesModule,
    TypeOrmModule.forRoot({   // 2
      type: 'postgres',
      host: process.env.DATABASE_HOST,
      port: +process.env.DATABASE_PORT,
      username: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE_NAME,
      autoLoadEntities: true,
      synchronize: true,
// ...
})


当我们交换位置,就会抛出错误!

@Module({
  imports: [
    TypeOrmModule.forRoot({     // 2
      type: 'postgres',
      host: process.env.DATABASE_HOST,
      port: +process.env.DATABASE_PORT,
      username: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE_NAME,
      autoLoadEntities: true,
      synchronize: true,
    }),
    ConfigModule.forRoot({  // 1
      load: [appConfig],
    }),
// ...
})


顺序很容易被忽略,我们应该怎么解决防止将来出现这个问题呢?

    TypeOrmModule.forRootAsync({   // 2  // forRootAsync以及useFactory
      useFactory:()=>({
        type: 'postgres',
        host: process.env.DATABASE_HOST,
        port: +process.env.DATABASE_PORT,
        username: process.env.DATABASE_USER,
        password: process.env.DATABASE_PASSWORD,
        database: process.env.DATABASE_NAME,
        autoLoadEntities: true,
        synchronize: true,
      })
    }),
    ConfigModule.forRoot({   // 1
      load: [appConfig],
    }),
目录
相关文章
|
9月前
|
API 网络架构
初识nest.js的controller(入门)
初识nest.js的controller(入门)
|
10月前
|
设计模式 开发框架 缓存
知道了,去卷后端 →「Nest.js 入门及实践」:)
知道了,去卷后端 →「Nest.js 入门及实践」:)
82 0
|
10月前
|
JSON 前端开发 JavaScript
NEST.JS使用心得
NEST.JS使用心得
|
12月前
|
存储 关系型数据库 测试技术
快速入门nest.js(10/10)--测试
初识Jest 很好的错误消息和内置Mocking实用程序 可靠的并行运行测试 优先运行以前失败的测试 根据测试文件花费的时间重新组织测试运行
265 0
|
12月前
|
存储 缓存 中间件
快速入门nest.js(8/10)--其他更多模块
嵌套构建块可以是: 全局范围 控制器范围 方法范围 参数范围<仅适用于管道>
97 0
|
12月前
快速入门nest.js(1/10)--Controller
这里的coffee字符将我们的应用程序的/coffee url绑定到了这个控制器上,此时如果直接像 http://localhost:3000/coffees 请求会404,因为我们还没有在这个控制器中设置一个GET路由
70 0
|
12月前
快速入门nest.js(3/10)--Module
最初我们将CoffeesController和CoffeesService作为AppModule的一部分,现在我们需要删除那一部分,否则会被实例化两次
60 0
|
12月前
|
PHP
快速入门nest.js(4/10)--DTO
简介:用于封装数据并将其从一个应用程序发送到另一个应用程序,帮助我们定义系统内的接口或输入和输出
242 0
|
JavaScript 前端开发
Nest.js学习笔记(七)
本节详细介绍Nest.js的控制器,以及使用Apifox做了简单的测试
230 0
|
存储 前端开发 机器人
Nest.js学习笔记(八)
本节利用Nest.js写了一个简单的session案例,实现了前后端验证码交互
80 0