原文地址:https://lon.im/post/use-envir...javascript
本文主要分析使用環境變量管理前端項目時會遇到的問題,並介紹經常使用工具給出解決方案。html
在搭建基於 webpack 前端項目時(或任意基於 Node 的項目,本文以 webpack 項目爲例),通常須要提供兩種運行模式:開發模式和生產模式。一般的作法是,執行命令前設置環境變量 NODE_ENV
爲 production
,如執行 NODE_ENV=production webpack
命令,而後在 JavaScript 代碼中經過 process.env.NODE_ENV === 'production'
來判斷是生產模式,不然爲開發模式。經過區分不一樣的模式能夠執行不一樣的操做,好比在開發模式下啓動開發服務器並代理轉發 API,或在生產模式下壓縮合並代碼等。爲了更好的統一前端工程命令,能夠將啓動開發模式和生產模式的命令分別加入 package.json 文件的 scripts 字段中,之後只須要執行 npm start
或 npm run build
便可。經過定義環境變量的方式很好的解決了在項目中執行差別操做的需求。若是但願支持成員自定義環境變量,只要在程序中優先使用環境變量中的值便可。好比已經設置端口號優先使用環境變量中的 PORT
的值,項目成員開發時執行 PORT=8080 npm start
命令就能夠自定義端口號爲 8080 了。前端
上述的解決方案能夠適用大部分場景,但卻沒法解決設置環境變量的跨平臺和持久化問題java
跨平臺node
若是項目中有使用 Windows 操做系統的成員,在執行 npm run build
(即 NODE_ENV=production webpack
)時會失敗,緣由是 Windows 命令不支持使用這種方式設置環境變量。雖然在 Windows 下也能夠根據 build 腳本內容,手動執行 set NODE_ENV=production webpack
,卻破壞了統一前端工程命令的初衷,爲此須要引入一個解決跨平臺設置環境變量的庫。如使用 cross-env,只要改寫 package.json 中的 build 腳本爲 cross-env NODE_ENV=production webpack
就能夠跨平臺工做了。webpack
持久化git
隨着規模的增大,項目自定義環境變量的數量可能愈來愈多。好比部署後靜態資源須要使用 CDN,項目生產模式就須要提供一個環境變量用於支持自定義 webpack 的 publicPath 字段;又好比有的成員並無把 API 服務器運行在本機,而是運行在虛擬機裏或另外一臺電腦上,項目開發模式就須要提供兩個環境變量用於支持自定義 API 服務器地址和端口號……可能有的成員每次開發時必須執行相似這麼長的命令:PORT=8080 API_SERVER=192.168.100.100 API_PORT=9000 npm start
,所以須要一個能夠持久化環境變量的工具,好比使用 dotenv 或 env-cmd 。以 env-cmd 爲例,只需建立一個 .env.local 文件(不計入版本管理),寫入:github
NODE_ENV=development PORT=8080 API_SERVER=192.168.100.100 API_PORT=9000
改寫 package.json 中 start 命令(build 命令相似)爲 env-cmd --fallback ./.env.local webpack
便可解決自定義環境變量過多每次手動輸入繁瑣的問題。web
管理環境變量有不少工具,下面簡單分析一下經常使用工具 dotenv、cross-env 和 env-cmd 的優點與不足:npm
事實上 NPM 自己也提供了相似設置項目環境變量的功能。以上述自定義端口號的需求爲例,也能夠在項目目錄下執行 npm config set project-name:PORT 8080
(project-name 爲項目名稱),執行 npm start
後在代碼中能夠經過 process.env.npm_package_config_PORT
獲取到 8080。並且還能夠將 package.json 中 config 字段設置爲 {"PORT": 8000}
,用於指定 npm_package_config_PORT
的默認值。使用 NPM 的 config 功能管理環境變量的最大優點是原生支持,放在 package.json config 字段中的默認環境變量也很是方便查看。遺憾是的,變量名前面都會有冗長的 npm_package_config_
;腳本必須從 package.json 的 scripts 字段中執行(即執行 npm run your_script_name);還有就是全部項目共用一份配置文件(.npmrc,默認在用戶目錄下),不方便手動編輯和查看。
所以一個好用的前端環境變量管理工具應該具有如下功能:
npm_package_*
和 npm_config_*
)爲此又誕生了一個環境變量管理工具:fuck-env,取義「惡搞環境變量」,支持以上全部功能。
fuck-env 安裝和使用
npm install fuck-env
若有一個包含 package.json 和 main.js 兩個文件的項目,文件代碼以下:
package.json
{ "name": "fuck-env-demo", "config": { "PORT": 8000, "APP_NAME": "$npm_package_name" }, "scripts": { "start": "fuck-env node main.js" }, "dependencies": { "fuck-env": "*" } }
main.js
console.log(process.env.PORT) // 8080 console.log(process.env.APP_NAME) // fuck-env-demo
執行 fuck-env PORT=8080 npm start
後,輸出「8080」和「fuck-env-demo」,不管是在 Windows 仍是 POSIX(macOS、Linux 等)系統中。
若是成員但願本地持久化自定義的端口號,能夠新建一個 .env 文件(此文件須加入 .gitignore,不計入版本管理,格式爲類 .ini 文件的簡單鍵值對)。
.env
PORT=8080
之後只需執行 npm start
便可。此外 fuck-env 還提供了另外一個命令行工具:fuck,用於快速設置本地環境變量。好比,若是成員又但願使用 9000 端口,能夠在項目根目錄下執行 fuck set PORT 9000
(需全局安裝 fuck-env),此時項目目錄下 .env 文件的內容即會變爲「PORT=9000」,使用 fuck 命令在環境變量較多時很是方便。
當環境變量過多時,所有放置 package.json 的 config 字段也會顯得臃腫。fuck-env 支持統一管理默認環境變量,只需將 config 字段下全部環境變量移至 default.env 文件(計入版本庫)中便可。
更多實例請參考這裏
fuck-env 致力於解決用戶管理環境變量時遇到的各類問題,將來會加入更多人性化設計。若是你有任何想法,歡迎給項目提出寶貴的建議。