詳解Nest.Js config 模組
前言
大約在2020年左右,Nest.Js官方推出了nestjs/config模組
早期的官方文章僅是很單純的自建config Module、ConfigService
直接在constructor用fs.readFileSync讀env檔,然後加個get function供其他模組使用
新推出的nestjs/config模組,完成度就很高了
讓參數檔可依模組劃分成獨立檔案,散落在各模組底下
可以直接注入單一參數檔來取得參數。甚至為了開發便利,注入的參數檔也能有語法糖帶出參數名
讓ide來除錯,大大降低了人為輸入錯誤的可能性
不過官方寫的相當粗淺,有點難以理解該如何使用…
僅就分享自己研究出來的使用方式
重點摘要
- 使用
forRoot()
、forFeature()
來載入參數檔 - 與TypeORM 或其他常見Module不同,
forFeature()
載入的參數,不需要在forRoot()
全部填上 forRoot()
僅需要載入AppModule
自己需要用到的就好- 以載入參數來使用這件事,
forRoot()
、forFeature()
使用體感是同樣的。當然底層forRoot()
還有其他用途(如cache),但就使用參數這件事較無感 - 官方文件是在
forRoot()
傳入validationSchema
來驗證參數。但沒有提到若多個參數檔該如何寫…看不太懂這塊該怎麼寫。若期望參數by模組畫分的話,驗證這塊個人偏好就直接寫在registerAs
裡了 - 若希望採用官方寫法
@Inject(databaseConfig.KEY)
,在開發時可以直接.
來取得參數,在registerAs
裡時會寫的比較醜一點,因讀檔時,當下不會知道到底讀到了什麼內容,除非自己又再加訂interface規範。但就有會有多餘…算是可妥協的小缺點 - 若要讀取參數實體檔(如
.yaml
),官方有提到nest-cli.json
須增加compilerOptions#assets
將靜態檔案拷貝至dist
底下,但官方範例又簡單到僅有單一目錄…。若參數檔想要by module置放的話,直接抄官方寫法會失敗。解決方式如後文參考
在nest-cli.json
增加靜態參數
yaml檔是一個很方便的格式,推薦大家使用此格式做為實體參數檔
官方亦有範例,不在贅述
打開nest-cli.json
,加入下列參數
"compilerOptions": {
"assets": [{"include": "**/*.yaml", "outDir": "./dist/src" }]
}
之後開發不論將.yaml
放在哪裡,打包後、開發期的runtime都會自動將yaml
檔放置對應位置
若副檔名習慣用.yml
,上述片段記得改成.yml
使用registorAs
注入config
依照官方教學,會是直接回傳yaml.load()
const YAML_CONFIG_FILENAME = `my-config.yaml`;
export default registerAs('myConfig', () => {
return yaml.load(
readFileSync(join(__dirname, YAML\_CONFIG\_FILENAME), 'utf8'),
) as Record<String, any>
});
但這樣做的缺點就是,無法使用官方推薦的@Inject(myConfig.KEY)
寫法,享有開發期的ConfigType保護
constructor(
@Inject(myConfig.KEY)
private myConfig: ConfigType<typeof myConfig>,
) {}
若想要同時保有讀.yaml
檔 及 ConfigType保護,則使用下列寫法
const YAML_CONFIG_FILENAME = `my-config.yaml`;
export default registerAs('myConfig', () => {
const yamlConfig = yaml.load(
// readFileSync(resolve(`config`, YAML_CONFIG_FILENAME), 'utf8'), // 若希望是放根目錄的config下,可以使用這個寫法
readFileSync(join(__dirname, YAML_CONFIG_FILENAME), 'utf8'),
);
return {
myConfig1: yamlConfig['myConfig1'],
myConfig2: yamlConfig['myConfig2'],
}
});
若有需要,亦可於此比照官方教學,增加Joi
等相關驗證功能
雖然仍有缺點
- 組
return的物件
仍沒有型別保護 - 參數異動時,要記得來這裡調整
return物件
但於service注入使用時,可以很舒服的用.
來取參數,也大大降低了拼錯的風險
參考資料
Nest.Js 官方文件 / configuration
stack overflow / NestJS copy assets files