以我用過 Django / Docker 的經驗,一般都是利用環境變數來作分離,程式在執行時,會去讀取環境變數來當作設定,盡量不依靠設定檔,進而達到 12 factor – config 的要求。
到了 Angular ,就需要做出調整。Angular 是需要先進行建置產出 javascript / html / css ,再把這些產出的檔案放到網頁伺服器,瀏覽器再去下載,所以完全沒辦法使用環境變數作為設定,必須要把設定寫到檔案裡,再做建置。那設定寫到檔案的話,其實我們都知道,這些敏感設定內容不適合放到 git repository,即使是 private repository,這樣會有安全上的風險。那這樣就兩難了啊?
說來很妙,我是覺得官方早就應該有比較好的作法了,但是,並沒有。不管怎麼樣,我還是找到解決方法了,基本上跟我想的也差不多。
- GitHub Actions: Hide And Set Angular Environment Variables
- How to pass environment variables at building time in an Angular application using .env files
這兩篇文章的作法大同小異,這邊作簡單的說明:
- 移除 src/environment/environment.ts
- 新增一個腳本,這個腳本會讀取環境變數,並產生一個新的 src/environment/environment.ts
- 修改 package.json
- 在 scripts 裡增加 config,這個 config 會去執行步驟 2 的腳本,用以產生 environment.ts
- 修改 scripts 裡的 start / build,在執行原來的指令前,先執行 npm run config 去產生 environment.ts
下面兩個片段是關鍵的改動部分:
// set-env.ts // 放在專案根目錄下 import { writeFile } from 'fs'; import { name, version } from './package.json'; // Configure Angular `environment.ts` file path const targetPath = './src/environments/environment.ts'; // 載入 colors 模組,主要是用來顯示 const colors = require('colors'); // 可以把敏感內容放到 .env 檔案裡,nodejs 會把內容讀出來,放到環境變數裡 // 也可以在執行 npm run 之前,先設定好環境變數 const result = require('dotenv').config(); if (result.error) { // throw result.error; } // 原來 environment.ts 裡的內容,把該替換的,用 template literals 來替換 // https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Template_literals const envConfigFile = `export const environment = { production: ${process.env.PRODUCTION}, VERSION: '${version}’, }; `; // 顯示 console.log(colors.magenta('The file `environment.ts` will be written with the following content: \n')); console.log(colors.grey(envConfigFile)); writeFile(targetPath, envConfigFile, (err) => { if (err) { throw console.error(err); } else { console.log(colors.magenta(`Angular environment.ts file generated correctly at ${targetPath} \n`)); } });
// package.json // 只摘錄重要的部分 { “scripts”: { "config": "ts-node -O '{\"module\": \"commonjs\"}' ./set-env.ts", "start": "npm run config && ng serve", "build": "npm run config && ng build” } }
沒有留言:
張貼留言