在現代前端項目中.env
文件隨處可見,裏面都是一些項目中的配置項,能夠在項目中拿來就用,雖然這是一個不太起眼的東西,可是這些.env
文件在前端工程化中是有必定的用處和意義的。javascript
就讓咱們經過這篇短文一塊兒來看看。前端
如今的前端項目都是用 Node
來做爲輔助開發工具,而 process
是 Node.js
中的 一個全局變量,提供來有關當前 Node.js 進程的信息並對其進行控制。而 process
中的 env
則是返回包含用戶環境的對象。java
通俗點說,就是能夠經過 process.env
拿到當前項目運行環境的信息。node
Mac下的基本環境信息:git
// index.js
console.log(Object.keys(process.env));
複製代碼
當須要在環境變量中加入自定義的一些配置,能夠直接經過命令行的方式來進行設置:github
console.log(process.env.PROT)
複製代碼
PROT=10086 node index.js
複製代碼
此時項目運行的環境變量中就有了 PROT
。數據庫
若是須要自定義其餘變量,能夠以鍵值的方式繼續添加參數:npm
PROT=10086 NDOE_DEV=development node index.js
複製代碼
這樣的方式雖然很簡單,可是也有不少缺陷:前端工程化
因此就有了下面一種方式。api
直接在項目根目錄中建立 .env
文件,而後鍵入環境變量及其值。
NDOE_ENV=development
PROT=10086
APP_KEY=***********
HOST_URL=**********
複製代碼
⚠️注意:不要把.env
文入放入代碼版本管理中,由於這些環境變量都是項目中的隱私數據,不然將面臨被暴露的風險。
建立 .env
文件後,能夠本身編寫代碼來查找解析文件並將其寫入到你的項目中,或者利用第三方的npm
包,好比 dotenv
,點擊這裏查看repo。
yarn add dotenv
複製代碼
// .env
PROT=10086
複製代碼
const dotenv = require('dotenv');
dotenv.config();
console.log(process.env.PROT); // 10086
複製代碼
如今當你執行命令腳本的時候就不用傳入環境變量及其值了,在 .env
文件裏也能更直觀的看到和管理各環境變量的配置。
若是不進行環境變量的組織,那麼在使用的時候就會像這個樣子:
process.env.PORT
複製代碼
可是一旦環境變量不少,是在每一個地方都這樣使用呢?仍是將全部的環境變量集中管理更好呢?
顯然是後者。
由於在全部須要使用的地直接引用變量與集中管理相比,重構和維護會更加困難。
因此建立一個負責收集環境變量的模塊是一個更好的方式,這樣能夠輕鬆地一次查看環境變量並將它們映射爲可讀的名稱。
建立一個名爲 config.js
的文件,而後寫入變量,將其命名爲具備良好可讀性的屬性進行映射並導出它們。
例如:
const dotenv = require('dotenv');
dotenv.config();
module.exports = {
hostUrl:process.env.HOST_URL,
secretKey:process.env.API_KEY,
port:process.env.PORT
};
複製代碼
而後就能夠這樣進行使用:
const {port} = require('./ config');
console.log(`端口爲:$ {port}`); // 10086
複製代碼
這樣有什麼好處呢?
可是若是要添加新的環境變量時,就必須將其添加到config
模塊中。
這就是手動的方式,那麼有自動收集方式嗎?
固然有!
前面提到的第三方 NPM
包 dotenv
就能夠作到。
// config.js
const dotenv = require('dotenv');
const result = dotenv.config();
if (result.error) {
throw result.error;
}
const { parsed: envs } = result;
console.log(envs);
module.exports = envs;
複製代碼
而後就能夠其餘模塊中這樣引用:
const { HOST_URL, API_KEY, PROT } = require('./config');
複製代碼
因此如今須要用哪種方式,這就取決於你了,不管哪種方式,你得考慮如下是否讓dotenv
成爲項目運行的依賴項。
建議使用手動的方式進行整理環境變量,這樣還能夠刪除 dotenv
的依賴,但前提是須要再作一下處理: 預加載環境變量。
在平時的項目中會有不少依賴,可是應該考慮如何將依賴性下降到最低,dotenv
這個 npm
包的確很方便,但這個不須要成爲項目運行時的依賴。dotenv
提供了一個選項,您能夠在其中預加載代碼以外的變量。
可是如何刪除 dotnev
運行時的依賴,而後又保留它的特性呢?
一、在安裝 dotenv
的時候,安裝爲開發(dev)依賴,刪除 dotenv
全部相關代碼。
二、而後使用 -require(-r)
這個選項來進行預加載 dotenv
。
// config.js
module.exports = {
port: process.env.PORT
};
複製代碼
// index.js
const {port} = require('./config');
console.log(`端口號爲:${port}`);
複製代碼
node -r dotenv/config index.js
複製代碼
看到了這裏,有人會說,開發環境(development)是能夠經過 dotenv
的預加載來讀取環境變量,但在生產環境(production)咋辦?
在構建應用程序的12要素指南中也指出應用程序須要和配置進行分離,最好的方式就是保存在環境變量中,覺得這些配置基本都是端口號、服務帳戶憑證、數據庫連接等私密信息,若是項目中的配置是保存在代碼中的,或者加入了代碼的版本管理,那麼你的項目暴露這些私密信息的概率是很大的。
若是你還不瞭解什麼是12要素,你能夠看看《漲知識了!用這 12 要素來構建你的應用程序》一文。
因此根據 配置項(config) 這一要素來看,.env
文件是一個私密文件,也不該該加入版本控制。
若是運行上雲服務器上,則能夠用雲服務商提供的功能來進行設置。或者使用第三方的服務平臺 Azure 來管理環境變量。能夠經過它的 CLI 啓動 Node 項目,而後就能夠從雲服務平臺拿到環境變量信息。
若是在 Docker
中運行,則可使用 Docker
的功能來加載環境變量。
對於生產環境如何對環境變量進行配置的細節將會在以後的文章就行闡述。
因爲.env
文件是保存項目的配置信息,這些信息都是私密的,不能對外暴露的,那麼如何與項目組內其餘同時共享這些配置信息呢?
能夠在項目根目錄新建 .env.example
文件,寫好全部環境變量的鍵值,而後能夠寫入假值或者鍵值的描述,在項目的 README.md
文件中進行說明如何獲取設置環境變量的值。
例如:
// .env.example
APP_ENV=development
NODE_ENV=development
HOST=app.test.com
PORT=10086
GOOGLE_MAP_API_KEY=the-google-map-api-key
複製代碼
環境變量配置信息也能夠保存在第三方的儲存管理系統,例如 Vault 提供了對 Token,密碼,證書,API key等的安全存儲(key/value)和控制。
經過自建服務或者 Azure 開源的持久化配置服務,而後在服務器利用 SDK 來獲取環境變量。
不過通常的雲服務商都會打包這項服務,由於只有服務器和持久化配置服務都由一個供應商提供,供應商才能將持久化配置與服務器權限造成關聯,讓第三方服務器即使拿到 Token 也沒法訪問配置。
若是項目的安全級別比較高,那麼可使用加密服務。
環境變量應該是存在於項目代碼以外的,它只在項目運行時可用,這樣使項目的配置與其代碼脫離,從而使項目能夠輕鬆地部署在不一樣的環境中。
對於以 Node.js
做爲輔助開發的現代前端應用,能夠經過process.env全局變量使用環境變量或者在運行node命令時設置環境變量,也可使用 dotenv
。
最後必定要注意 .env
文件永遠不該存在於源代碼存儲庫中,加入代碼的版本管理。
參考文章: