Node.js無處不在的環境變量!

您構建的 Node.js 應用程序首先要在計算機上運行。您知道,應用程序在任何須要運行的地方都能工做是很重要的。這多是在你同事的電腦、公司內部服務器、雲服務器或容器內部(可能使用Docker)。輸入環境變量.node

貼圖

使用環境變量的說明性指南git

環境變量是使用 Node.js 開發的一個基本部分,它容許您的應用程序根據您但願它們運行的環境而表現出不一樣的行爲。不管您的應用程序在哪裏須要配置,您均可以使用環境變量。它們很是簡單,並且很是漂亮!這篇文章將向您介紹如何建立和使用環境變量。docker

這篇文章將引導您建立和使用環境變量,從而建立一個能夠在任何地方運行的 Node.js 應用程序。數據庫


人們常常問我,我是如何決定什麼是學習和投入時間的,什麼是聽任自流的。對我來講,這是從這兩個相同的問題開始的(例如,問爲何和什麼時候)。我敢打賭,你也會作相似的事情,不是嗎?npm

爲何和何時?json

當有人告訴你某件事情很重要,你應該使用它時,我建議問兩個簡單的問題。api

  1. 爲何我應該使用它?
  2. 我應該在何時使用它(或不使用它)?

**爲何?

如今是你問我爲何要使用環境變量的時候了。去吧;不要緊。安全

若是您關心使您的應用程序在任何計算機或雲上運行(也就是您的環境),那麼您應該使用它們。爲何?由於它們將您的應用程序的全部環境特定方面外部化,並保持您的應用程序封裝。如今,您能夠經過修改環境變量在任何地方運行您的應用程序,而無需更改您的代碼,也無需從新構建它! **何時?服務器

**何時?

好了,如今你問我何時應該使用它們。簡而言之,你的代碼中任何會根據環境而改變的地方。當你看到這些狀況時,對任何你須要改變或配置的地方都要使用環境變量。編輯器

下面是一些你應該考慮使用環境變量的常見場景的具體例子。

  • 偵聽哪一個HTTP端口
  • 您的文件在什麼路徑和文件夾中,您想提供的服務

*指向開發、暫存、測試或生產數據庫。

其餘的例子多是服務器資源的URL,測試與生產的CDN,甚至是在UI中經過你的應用所處的環境來標記你的應用。

讓咱們來探討一下如何在Node.js代碼中使用環境變量。

使用環境變量

您可能正在爲 Express 服務器設置端口號。一般狀況下,不一樣環境(例如;暫存、測試、生產)中的端口可能須要根據策略進行更改,並避免與其餘應用程序發生衝突。做爲開發人員,你不該該關心這些,實際上,你也不須要關心。下面是如何在代碼中使用環境變量來抓取端口。

// server.js
    const port = process.env.PORT
    console.log(`Your port is ${port}`);

試試這個。建立一個名爲 "env-playground "的空文件夾。而後建立一個名爲server.js的文件,並將上面的代碼添加到其中。如今,當你執行node server.js時,你應該看到一條消息說 "Your port is undefined"。

你的環境變量不在那裏,由於咱們須要把它們傳遞進來。讓咱們考慮一些能夠解決這個問題的方法。

1.使用命令行

  1. 使用.env文件。

命令行

將 port 傳入您的代碼的最簡單方法是在命令行中使用它。在命令行中指定變量的名稱, 後面是等號, 而後是值。而後調用您的 Node.js 應用程序。

PORT=8626 node server.js

你會看到端口顯示在這樣的消息中:"你的端口是8626"。

_這個8626是什麼東西?爲何不是4200或者3000或者更傳統的端口?好吧,我是迪斯尼的忠實粉絲,有一個叫史迪奇的角色也被稱爲實驗626._。

你能夠重複這個模式,也能夠添加其餘變量。下面是一個傳遞兩個環境變量的例子。

PORT=8626 NODE_ENV=development node server.js。

按照環境變量名後加等號再加值的模式。這很容易作到,但也太容易犯輸入錯誤了。這就有了下一個選項。

減小.env文件的混亂

一旦你定義了其中的幾個,你腦海中的下一個念頭可能就是如何管理它們,使它們不會成爲維護的噩夢。想象一下,數據庫鏈接、端口和密鑰都有好幾個。當你把它們都打在一條線上時,這並不能很好地擴展。並且可能會有私人信息,如密鑰、用戶名、密碼和其餘祕密。

從命令行運行它們固然很方便。但它也有它的缺點。

  1. 沒有一個很好的地方能夠看到變量列表。

2.從命令行打字太容易出錯了。
3.要記住全部的變量和它們的值並不理想。
4.即便使用npm腳本,你仍然必須保持它們的最新性。

對於如何組織和維護環境變量,一個流行的解決方案是使用.env文件。我真的很喜歡這種技術,由於它使我能夠在一個地方快速讀取和修改它們變得超級容易。

在你的應用程序的根目錄下建立.env文件,並將你的變量和值添加到其中。

NODE_ENV=development
    PORT=8626
    _# 在這裏設置你的數據庫/API鏈接信息。
    _API_KEY=**************************
    API_URL=**************************

記住你的.gitignore文件

.env文件是一個很好的方法,能夠在一個地方看到全部的環境變量。只要確保不要把它們放到源代碼控制中。不然,你的歷史記錄將包含對你的祕密的引用。

建立一個.gitignore文件(或者編輯現有的文件,若是你已經有了),並添加.env到其中,以下圖所示。.gitignore文件會告訴源控制忽略你列出的文件(或文件模式)。

貼圖

貼圖

當心將.env添加到.gitignore文件中,並在添加你的_ .env_以前提交該更改。不然,你就有可能將你的 .env_的早期版本提交到源代碼控制中。

您能夠經過使用 Visual Studio Code (VS Code)中的命令調色板將一個文件添加到您的.gitignore文件中。按照如下步驟進行。

  1. 在VS Code中打開你要添加到.gitignore的文件。
    在Mac上用CMD+SHIFT+P打開命令調色板,在Windows上用CTRL+SHIFT+P打開。
  2. 輸入 "忽略"。
  3. 選擇 "Git: 從菜單中添加文件到.gitignore"

這將把你當前打開的文件名添加到.gitignore文件中。若是你沒有建立.gitignore文件,它將爲你建立!

貼圖

將.env加入到.gitignore中。

您的.env文件的語法高亮

若是你使用VS Code,你會想要添加dotenv擴展。這將爲你的.env文件的內容提供語法高亮,並使你更容易使用.env文件中的變量。

下面是安裝了dotenv擴展的VS Code中的文件。

貼圖

.env文件在VS Code中具備語法高亮功能。

讀取.env文件

如今你可能在想,有些東西必須尋找.env文件,你是對的!你能夠本身寫代碼來尋找文件,解析,並將它們讀到你的Node.js應用中。

你能夠寫你本身的代碼來找到這個文件,解析它,而後把它們讀到你的Node.js應用中。或者你也能夠經過npm找到一種方便的方法,將變量一次性讀到你的Node.js應用中。你極可能會遇到npm上的dotenv包,它是個人最愛,也是我推薦你使用的。你能夠像這樣npm install dotenv來安裝它。

而後你能夠在你的項目中要求使用這個包,並使用它的config函數(config也有一個load的別名,以防你在野外看到)來尋找.env文件,讀取你定義的變量,並將它們提供給你的應用程序。

按照如下步驟進行。

  1. 建立一個package.json文件

2.安裝dotenv的npm包。
3.寫代碼讀取.env
4.運行代碼

建立一個package.json文件

你須要一個package.json文件來配置你的版本,跟蹤你的依賴關係,幷包含你的npm腳本。經過運行如下命令來實現

npm init -y

這將建立一個 "package.json "文件,其中包含基本設置。

從npm安裝dotenv

你須要讀取.env文件,而npm上的dotenv包能夠很好地完成這個任務。運行如下命令安裝dotenv包

npm install dotenv

這將把dotenv包和它的文件添加到你的node_modules文件夾中,並在package.json文件中爲dotenv建立一個條目。

讀取.env文件

是時候用一點代碼讀取.env文件了。用下面的代碼替換你的server.js文件的內容。

// 服務器.js
console.log(Your port is ${process.env.PORT}); _// undefined
_const dotenv = require('dotenv');
dotenv.config();
console.log(Your port is ${process.env.PORT}); _// 8626_。

該代碼顯示了PORT環境變量的初始值,該變量將是未定義的。而後,它須要dotenv軟件包,並執行其config函數,讀取.env文件並設置環境變量。最後一行代碼顯示 "PORT "爲8626。

運行代碼

如今,使用如下命令,在不傳遞端口的狀況下,在命令行中運行代碼

node server.js

請注意控制檯日誌信息顯示端口最初是未定義的,後來變成了8626。dotenv軟件包讀取並設置這些值,其實是爲您作了骯髒的工做。

輕鬆找到您的變量

如今,咱們有了一個在.env文件中建立變量的單一地方,咱們可能會考慮如何在Node.js代碼中輕鬆檢索全部這些變量。爲何要這樣作?這個問題問得好! 好吧,你能夠在代碼中使用如下語法來引用變量。

process.env.YOUR_ENV_VAR_GOES_HERE

可是,你是否想在你須要的地方都這樣作(你可能在多個地方須要它們)?仍是應該把咱們全部的環境變量收集在一個地方? 固然是後者! 爲何這麼說呢? 若是你真的在全部須要的地方都引用變量,可能會比在一個地方引用變量更難重構和維護。

我建議建立一個模塊,負責收集環境變量。這樣能夠很容易地一次性看到它們,並將它們映射到可讀的名稱上。

這裏有兩個不錯的選擇能夠考慮。

  1. 在一個模塊中手動設置和導出它們。

2.使用一個庫來讀取並在一個模塊中導出它們。

這兩種技術都涉及建立一個模塊,但它們在環境變量的映射和暴露方式上有所不一樣。讓咱們仔細看看這兩種技術,並權衡一下它們的區別。

手動組織

建立一個模塊(下面的例子顯示的是config.js),在這個模塊中,你能夠收集變量,將它們映射爲名稱明確且可讀的屬性,並將它們導出。

讓咱們在一個名爲config.js的文件中建立一個新模塊。而後將如下代碼複製並粘貼到文件中。

// config.js
    _const_ dotenv = require('dotenv');
    dotenv.config();
    module.exports = {
      endpoint: process.env.API_URL,
      masterKey: process.env.API_KEY,
      port: process.env.PORT
    };

這個例子展現了咱們如何將環境變量整合到一個文件中。

讓咱們再次修改server.js,此次是導入config.js模塊並使用它來訪問咱們的環境變量。用下面的代碼替換server.js的內容。

// server.js
    _const_ { port } = require('./config');
    console.log(`Your port is ${port}`); _// 8626_

使用node server.js運行代碼,你會看到 "你的端口是8626 "的消息。環境變量正在被config.js文件中的dotenv代碼讀取。你的server.js文件導入config.js中的模塊並提取端口變量。

你能夠把config.js文件導入到你須要的地方,而後用destructuring來提取你須要的東西。你只調出了port,但你固然能夠調出模塊中導出的任何一個值。

const { endpoint, masterKey, port } = require(‘./config’);

這個技術有什麼價值?

1.它很容易
2.明確全部環境變量的映射方式。
3.你能夠將變量重命名爲更易讀的屬性。
4.你能夠從非環境變量中添加其餘配置屬性。

這裏的關鍵點是,config模塊的目的變成了收集和暴露全部的配置,無論它來自哪裏。

使用庫進行整理

手動技術的一個後果是,當你添加一個新的環境變量時,你必須把它添加到config模塊中。例如,若是你須要製做一個新的變量,你須要進入這個配置模塊,並添加這樣的內容。

visionApiUrl=process.env.VISION_API_URL

我不介意這個後果,由於不管如何我都要經過個人代碼來使用新的值。但我指出這一點是由於有一種方法能夠自動收集它們。

dotenv npm包中的dotenv.config()函數會讀取.env文件,將變量分配給process.env,而後返回一個包含內容的對象(命名爲parsed),若是失敗的話,它還會拋出一個錯誤。

下面的代碼讀取.env文件,並收集envs對象中的變量。

// 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 { endpoint, masterKey, port } = require(‘./config’);

你應該用哪一個方案?這由你本身決定。但請考慮是否要將npm包dotenv做爲運行時依賴。也許在更高的環境(好比生產環境)中,還有其餘的方法來獲取環境變量,在這些環境中,安全是最重要的。你甚至但願你的node應用中的代碼可以讀取如此重要的文件嗎?你可能會以爲很酷,但若是有一種方法能夠讀取變量,並在你的package.json文件中把dotenv包變成一個devDependency呢?

我建議你使用第一種技術,即在模塊中手動設置環境變量,好比config.js。這容許你刪除dotenv做爲運行時的依賴--假設你還作了一件事:預加載環境變量。這也容許你減小你的運行時依賴性。

減小您的依賴性

你有不少對npm包的依賴。當你計劃你的應用程序的生命週期和維護時,每個都是你應該考慮的。你可能已經在考慮如何將你的依賴性減小到最低限度。我也是這樣作的。

dotenv包是很棒的,但咱們不須要它成爲運行時的依賴。dotenv包提供了一個選項,你能夠在你的代碼以外預加載變量。你能夠加載變量,並從咱們的代碼中刪除讀取.env文件的代碼。更少的代碼就是更少的行數,可能會中斷或被維護。

還不放心嗎?您是否考慮過如何在雲中訪問這些環境變量?你但願你的代碼試圖讀取一個文件嗎?我對此投了一個響亮的 "不"。我更但願個人代碼不要試圖讀取文件,由於若是我把它帶到雲端,我但願這些解決方案甚至沒有.env文件。

如何從咱們的代碼中刪除dotenv的運行時依賴,但又不失去已經得到的價值?首先,在安裝dotenv npm包的時候,你能夠像這樣把它保存爲開發依賴關係。

npm install dotenv --save-dev。

而後刪除全部在dotenv上使用require的代碼,包括本文以前提到的dotenv.config()代碼。這包括本文前面提到的dotenv.config()代碼。

如今的問題是,你以前是依靠dotenv來加載環境變量的。這就是預加載選項發揮做用的地方。

你可使用- require ( -r ) 命令行選項來預加載dotenv來運行你的node應用。下面的命令將使用dotenv從文件.env中預載全部環境變量,並使它們在你的應用程序中可用。因此你如今已經從你的代碼中刪除了全部對dotenv的引用。

node -r dotenv/config server.js

當你想讓你的應用運行在文件不存在(也許不該該存在)的地方時,這頗有用,好比在運行中的docker容器或雲服務器中。能夠從node -h內看到-r選項的說明:

-r, --require=...                   module to preload (option can be repeated)

Leveraging npm Scripts

我強烈建議把你的命令放到一個npm腳本中。這使得它更容易運行,而不是輸入全部這些標誌。也許你能夠爲它建立一個自定義腳本或者使用npm啓動腳本。下面是你使用自定義腳本時腳本的樣子。

scripts: {
      "start_local": "node -r dotenv/config server.js"
    }

命令npm run start_local就會啓動這個命令。固然,你能夠隨意命名這個腳本。

爲何不使用npm start?問得好,你固然能夠這樣作。你固然能夠這樣作。我喜歡把npm start保留給我在沒有docker容器的狀況下如何在生產中運行它,這可能只是像這樣。

scripts: {
      "start": "node server.js"
    }

這裏的關鍵是,不管使用哪一種npm腳本,你都在運行徹底相同的node代碼!區別在於你的變量如何設置。區別在於如何設置你的變量。你如今已經從你的應用程序中抽象出了你的配置。

好的npm工具

如何記住全部的npm腳本?這很簡單 - 你不須要!我依靠偉大的工具來幫助運行個人npm腳本。雖然我喜歡僞裝我知道全部的腳本名稱和它們的具體做用,但事實上,我更但願有一個工具能夠顯示出列表,我能夠選擇它。

在我選擇的代碼編輯器中,有兩個很棒的工具能夠作到這一點。VS Code

1.npm的腳本大綱

  1. npm擴展

npm腳本大綱是內置在VS Code中的,並顯示在資源管理器視圖中。請注意下面的截圖顯示了個人package.json文件中的npm腳本,若是你在你的項目中沒有看到這個,請確保將npm.enableScriptExplorer設置爲true。若是你在你的項目中沒有看到這個,請確保在VS Code的settings.json中把npm.enableScriptExplorer設置爲true。

你能夠右鍵點擊一個npm腳本,而後打開、運行或調試它。

貼圖

若是你像我同樣喜歡用手敲鍵盤,那麼你可能更喜歡VS Code的npm擴展。在安裝了VS Code的npm擴展以後,你就能夠在命令板上運行npm腳本了,在Mac上只要輸入CMD+SHIFT+P就能夠了。

只要在Mac上輸入CMD+SHIFT+P,或者在Windows上輸入CTRL+SHIFT+P。而後開始輸入npm,選擇 "npm: 運行腳本",以下圖所示。

貼圖

而後你會看到一個npm腳本的列表。從這裏開始,你能夠開始輸入你想要的腳本的名字,直到你想要的腳本被高亮顯示。或者你使用箭頭選擇你想要的腳本。而後按 "ENTER "來運行它。

我喜歡這樣,由於它讓個人手放在鍵盤上,這感受比在鼠標/觸控板和鍵盤之間切換更有效率。

給一個這樣的嘗試。

不管在哪裏運行,你的代碼都是同樣的。

你的應用程序沒有意識到環境變量的來源。您運行它的方式,即預加載,是在您的本地機器上提供它們。

讓咱們進一步探討爲何你可能但願你的應用程序對其配置沒有意識。

Docker容器

想象一下,咱們正在一個Docker容器中運行。容器的傳統指導說,容器內的應用不該該知道它們的配置。這樣一來,只要容器和運行容器的任何東西就必須提供哪些變量達成協議,容器就能夠在任何地方運行。

在雲端運行的

當你把咱們的應用帶到雲端時,各類雲提供商也都有辦法讓你設置環境變量。所以,再次強調,若是應用程序僅僅使用變量,而運行它的東西(在這種狀況下,雲提供商的服務)爲您提供了定義這些變量的方法,您就能夠了。

  • 你的應用程序與其配置的這種分離,很大程度上來自於被稱爲12因素的指導。若是你尚未閱讀過這方面的內容,請在這裏瞭解更多_ https://12factor.net__。

與您的團隊分享

你的隊友如何知道要爲你的應用建立哪些環境變量?他們應該在你的代碼中搜索這些變量嗎?他們應該打電話問你嗎?固然不是,你沒有時間親自去拜訪每個開發者!

當你的.env文件沒有被推送到源碼控制中時(這是不該該的),重要的是要讓你們清楚這個文件的形狀應該是什麼樣的。我推薦的技術是建立一個名爲.env.example的文件,其中包含變量,但使用假值。這個文件可能看起來像下面的模板。

.env.example

NODE_ENV=開發
PORT=8626
# 在這裏設置你的數據庫鏈接信息 API_KEY=your-core-api-key-goes-here

你的團隊能夠把這個文件的內容複製到他們本身的.env文件中,而後輸入他們須要的值。在示例文件中列出非機密的值是徹底正常的。注意到.env.example文件中的PORTNODE_ENV都被設置了,但API_KEY沒有被設置。明智地選擇你推送到源代碼控制的內容。

而後,你能夠在你的README.md中引用這個文件,你的隊友能夠很快學會如何設置本身的值。問題解決了。

環境變量的做用

這只是對如何使用環境變量以及一些可使用環境變量的神奇工具的一瞥。總的來講,我建議你使用環境變量,並遵循如下步驟。

  1. 建立一個.env文件

2.在你的.gitignore文件中忽略它。
3.使用VS Code來編輯你的.env文件。
4.安裝VS Code的dotenv擴展
5.安裝VS Code的npm擴展
6.讀取dotenv npm包中的.env文件做爲開發依賴。
7.使用dotenv的預加載選項來刪除對它的任何運行時引用。
8.使用npm腳原本運行你的node應用。
9.爲你的變量建立一個名爲.env.example的模板文件。

若是你喜歡我使用的字體和主題,它們是Dank Mono和Winter is Coming (Blue)。你能夠找到 這裏的Dank Mono字體 並安裝 這裏的Winter is Coming主題_。我最後一次檢查時,字體的價格是40英鎊,而主題是免費的_。

可是等一下,你想讓你的服務器有一個免費的字體嗎?你但願你的服務器有一個.env文件嗎?你使用Docker或雲服務器嗎?這些都是要問本身的好問題。你在這裏學到的方法是一個基礎,能夠與其餘解決方案協同工做。我很快會在將來的文章中深刻探討這個問題,敬請期待。

相關文章
相關標籤/搜索