前言

本地开发与正式环境有些配置是不一样的,比如:数据库的链接配置、环境标识NODE_ENV等、以及一些静态的全局变量之类的数据;

nest主张的是模块化的形式,所以将这些东西全部包成一个模块注册使用是一个不错的办法,那么有什么便捷的处理方式呢?

nest官方提供了一个插件:@nestjs/config

用于处理这些东西,以及提供便捷的类型推断方式。

插件文档地址:使用文档

首先我们需要安装这个插件:

pnpm i @nestjs/config

环境变量区分

我们在项目中创建一个.env的环境变量文件,这个文件只会在各自的本地存在,如果我们使用了git仓库来进行管理的话,这个文件是需要在.gitignore中禁止上传的。

我们可以提供一个.env.example文件来作为环境变量的示范文件,项目需要正式启动的时候,将.example去掉,并将环境变量中具体的值改为正确的内容。

这样的话就可以方便的区分本地开发环境和线上开发环境,不需要将一些私密的数据上传了。

我们可以写入一些常用的数据:

NODE_ENV=development

配置完毕后我们继续往下走。

模块注册和使用

我们在app.module.ts中注册这个插件:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [ConfigModule.forRoot()],
})
export class AppModule {}

一般情况下我们的这个模块是需要给所有人使用的,那么就需要将其设置为全局模块。

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,  //设置为全局模块
    })
  ],
})
export class AppModule {}

使用的时候我们可以在对应的服务里面注入:

import { Injectable} from  "@nestjs/common";

@Injectable()
export class AppService {
  constructor(private configService: ConfigService) {}

  getHello(): string {
    return  this.configService.get("NODE_ENV");  //development
  }
}

让我比较震惊的时它是怎么知道我注入的是这个模块的,emm,因为没有使用@Inject包装器,让我有点惊叹,毕竟类包装器@Injectable应该是拿不到具体的参数信息的啊?

这个以后明白了再细说吧!

注意:

get方法是可以传入一个泛型的。

this.configService.get<string>("NODE_ENV");

get还有第二个参数,用于获取不到的默认值处理,当然泛型也存在第二个:

this.configService.get<string, string>("NODE_ENV","production");

自定义变量(命名空间)

有的时候我们会有一些全局的自定义变量需要共享,但是通过get方法去获取的话是没有类型推断的,不会有ts属性提示这些,所以我们可以使用命名空间的方式来实现。

我们需要从模块中引入registerAs函数,通过这个函数传入一个工厂函数返回自定义变量。

import { registerAs } from "@nestjs/config";

export default registerAs("app", () => ({
  /** 端口 */
  port: 3000,
}));

然后我们在模块中通过load配置加载这个导出的函数。

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import appConfig from "./config/app";

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,  //设置为全局模块
      load: [ appConfig ]
    })
  ],
})
export class AppModule {}

然后在需要使用的地方通过Inject注入:

import { Injectable, Inject } from "@nestjs/common";
import { ConfigType } from "@nestjs/config";
import appConfig from "./config/app";


@Injectable()
export class AppService {
  constructor(@Inject(appConfig.KEY) private config: ConfigType<typeof appConfig>) {}

  getHello(): string {
    return this.config.port;
  }
}

配合ConfigType来获取工厂函数返回值的类型定义。

事实上load不一定非得是registerAs工厂函数,还可以是普通的函数返回对象的形式,具体可以去文档查看,但是这样的话就没法配合ConfigType做类型推断了,所以看自己需要可以自行决定。

分类: Nest.js 标签: 环境变量nest.js@nestjs/configConfigType

评论

全部评论 8

  1. alterass
    alterass
    Google Chrome Windows 10
    博主,这个和直接使用process.env拿到环境变量区别是啥?
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @alterass区别就是更加统一,通过模块化的方式,可以实现依赖注入来获取环境变量服务,通过服务再获取对应的环境变量值,其二就是这个模块化功能更强,你可以去看下这个插件的文档,除了读取env还能让他直接读取自己配的js导出对象。
      1. alterass
        alterass
        Google Chrome Windows 10
        @木灵鱼儿[响指]好的。如果是用ConfigService在imports注册JwtModule,是不是只能用JwtModule.registerAsync,而不能用JwtModule.register了?[思考]
        1. 木灵鱼儿
          木灵鱼儿
          FireFox Windows 10
          @alterass可以这么理解,在需要用到ConfigService的模块上,这个模块的注册一般推荐用registerAsync
          1. alterass
            alterass
            Google Chrome Windows 10
            @木灵鱼儿感谢解惑[抱拳]
  2. 测试评论
    测试评论
    Google Chrome Windows 10
    测试评论功能
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @测试评论你跑我这测试???
  3. 测试xss
    #" rel="external nofollow">测试xss
    Google Chrome Windows 10
    啊啊啊啊啊

目录