在實際項目開發(fā)中,前端 er 常常會面對多個環(huán)境的接口:開發(fā)環(huán)境拘荡、測試環(huán)境、生產(chǎn)環(huán)境接剩,所以項目中網(wǎng)絡請求的 baseUrl
也需要跟隨這些環(huán)境來變化办成。
但是,我們一般會使用像 create-react-app
或者 umi
這樣的腳手架來做項目的初始化搂漠,這些腳手架將 webpack
的配置黑盒化了,如何在不執(zhí)行 eject
操作的前提下優(yōu)雅地配置多個項目環(huán)境呢某弦?
在項目中最好不要一遇到問題就一鍵執(zhí)行
eject
操作桐汤,eject
操作是不可逆的,執(zhí)行之后會把所有細節(jié)都暴露在我們面前靶壮,讓項目目錄變得很龐大怔毛。
create-react-app 配置多環(huán)境接口
其實查看 create-react-app 的官方文檔可以發(fā)現(xiàn),create-react-app
默認是支持多個環(huán)境配置文件的:
.env
:默認腾降。.env.local
:本地覆蓋拣度。除 test 之外的所有環(huán)境都加載此文件。.env.development
,.env.test
,.env.production
:設置特定環(huán)境螃壤。.env.development.local
,.env.test.local
,.env.production.local
:設置特定環(huán)境的本地覆蓋抗果。
左側的文件比右側的文件具有更高的優(yōu)先級:
npm start
:.env.development.local
,.env.development
,.env.local
,.env
npm run build
:.env.production.local
,.env.production
,.env.local
,.env
npm test
:.env.test.local
,.env.test
,.env
(注意沒有.env.local
)
例如我們部門目前開發(fā)流程中只有開發(fā)環(huán)境和測試環(huán)境兩種接口(其中,本地開發(fā)和測試共用一個環(huán)境)奸晴,
所以冤馏,我需要將測試環(huán)境下打包時使用的接口地址指定為 env.development
中的接口地址,我分別寫了兩份配置文件 .env.development
以及 env.production
寄啼,但是根據(jù)以上create-react-app
的官方文檔逮光,在執(zhí)行 build 命令時,默認是加載 .env.production
文件中的變量墩划,所以我在測試服務器上執(zhí)行 npm run build
命令時就會使得接口地址被指定為生產(chǎn)環(huán)境的接口地址涕刚,這顯然不是我想要的。
怎么辦呢乙帮?
官方文檔也給了我們答案——可以使用 dotenv 來做環(huán)境變量的管理(dotenv
可將環(huán)境變量從 .env 文件加載到 process.env
中杜漠。)
因為我們要在命令行中使用,所以我們需要使用 dotenv-cli蚣旱。
話不多說碑幅,讓我們開始吧~
寫好各個環(huán)境的配置文件
首先,我們可以寫好每個環(huán)境下的配置文件塞绿。
# .env.development
REACT_APP_BASE_URL='http://development.xxx.xxx'
# env.production
REACT_APP_BASE_URL='http://production.xxx.xxx'
修改 package.json
中的 scripts
來指定環(huán)境
"scripts": {
"start": "react-app-rewired start",
"build:dev": "dotenv -e .env.development react-app-rewired build",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
}
這樣沟涨,當我需要在測試服務器上打包前端代碼時,我就可以執(zhí)行npm run build:dev
來指定使用 .env.development
中的環(huán)境變量了~
umi
配置多環(huán)境接口
有了以上的經(jīng)驗我們就可以知道异吻,其實多環(huán)境配置裹赴,不外乎就是將各個環(huán)境的配置文件分開喜庞,并使用額外的手段來在打包時指定對應環(huán)境的配置文件。
寫好各個環(huán)境的配置文件
查看 UMI 文檔 可知棋返,環(huán)境變量被放在 config/config.js
下的 define 這個配置中延都,
如果你使用 TypeScript 開發(fā),那么配置文件是 config/config.ts睛竣。
所以同樣的晰房,我們可以將原來的 config/config.ts
做個分身,寫兩份配置文件射沟,分別是 config/config.dev.ts
和 config/config.prod.ts
修改 package.json 中的 scripts 來指定環(huán)境
查看 umi
生成的模版項目中的package.json
可以發(fā)現(xiàn): umi
默認是使用 cross-env來為 umi
打包指定配置文件殊者。所以我們將package.json
中的 scripts
改寫如下:
"scripts": {
"start": "react-app-rewired start",
"build-dev": "cross-env UMI_ENV=dev umi dev",
"build-test": "cross-env UMI_ENV=test umi build",
"build-prod": "cross-env UMI_ENV=prod umi build",
},
Tips:將配置和代碼分開存儲
將配置和代碼分開存儲
因為各個環(huán)境的部署版本之間,配置文件的差異程度可能很大验夯,但是代碼基本是不變的猖吴。
當然,上面所說的配置文件不包括內(nèi)部應用程序的配置(例如挥转,你可能將路由寫成了配置文件)海蔽。
判斷一個應用是否正確地將配置排除在代碼之外,一個簡單的方法是看該應用的基準代碼是否可以立刻開源绑谣,而不用擔心會暴露任何敏感的信息党窜。——《The Twelve-Factor App》
反面教材
一個比較典型的反面教材就是在代碼中再寫一份類似 getBaseUrl.js
這樣的文件來做環(huán)境判斷:
// getBaseUrl.js
const TEST_DOMAIN = process.env.REACT_APP_BASE_URL
const PRODUCTION_DOMAIN = process.env.REACT_APP_PRODUCTION_BASE_URL
let domain = TEST_DOMAIN
switch (process.env.NODE_ENV) {
case 'development':
domain = TEST_DOMAIN
break
case 'production':
domain = PRODUCTION_DOMAIN
break
default:
domain = TEST_DOMAIN
break
}
export default domain
上面的變量是 .env
文件里面寫好的變量:
# .env
REACT_APP_DEVELOPMENT_BASE_URL='http://xxxxxx' # 開發(fā)環(huán)境/測試環(huán)境的接口地址
REACT_APP_PRODUCTION_BASE_URL='http://xxxxxx' # 生產(chǎn)環(huán)境的接口地址
其實我自己在剛開始用 React 寫項目的時候就是這么干的??借宵,這樣相當于將配置寫在了代碼里面刑然,不僅可維護性比較差,而且別人看你代碼的時候暇务,可讀性也比較差泼掠。
配置文件區(qū)分環(huán)境,相互獨立
其實這種方式是 dotenv 所不推薦的垦细,它的觀點如下:
dotenv 推薦直接在配置文件直接存儲在不同的部署環(huán)境中择镇,不做版本控制,所以你需要在各個環(huán)境配置好環(huán)境變量括改,它們都放在 .env 文件中腻豌。但是這個對于我們小作坊式開發(fā)來說,反而比較麻煩嘱能,所以我目前都是按照分配置文件的方式來實踐的吝梅,如果正在閱讀本篇文章的你有更好的方式,歡迎評論~