優(yōu)雅實現(xiàn) React 項目多環(huán)境打包

知乎配圖

在實際項目開發(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.tsconfig/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 所不推薦的垦细,它的觀點如下:

image-20191206213457315

dotenv 推薦直接在配置文件直接存儲在不同的部署環(huán)境中择镇,不做版本控制,所以你需要在各個環(huán)境配置好環(huán)境變量括改,它們都放在 .env 文件中腻豌。但是這個對于我們小作坊式開發(fā)來說,反而比較麻煩嘱能,所以我目前都是按照分配置文件的方式來實踐的吝梅,如果正在閱讀本篇文章的你有更好的方式,歡迎評論~

參考文件

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惹骂,一起剝皮案震驚了整個濱河市苏携,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌对粪,老刑警劉巖右冻,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件装蓬,死亡現(xiàn)場離奇詭異,居然都是意外死亡纱扭,警方通過查閱死者的電腦和手機牍帚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乳蛾,“玉大人暗赶,你說我怎么就攤上這事∷嘁叮” “怎么了忆首?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長被环。 經(jīng)常有香客問我,道長详幽,這世上最難降的妖魔是什么筛欢? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮唇聘,結果婚禮上版姑,老公的妹妹穿的比我還像新娘。我一直安慰自己迟郎,他們只是感情好剥险,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宪肖,像睡著了一般表制。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上控乾,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天么介,我揣著相機與錄音,去河邊找鬼蜕衡。 笑死壤短,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的慨仿。 我是一名探鬼主播久脯,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镰吆!你這毒婦竟也來了帘撰?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤万皿,失蹤者是張志新(化名)和其女友劉穎骡和,沒想到半個月后相赁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡慰于,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年钮科,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片婆赠。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡绵脯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出休里,到底是詐尸還是另有隱情蛆挫,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布妙黍,位于F島的核電站悴侵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏拭嫁。R本人自食惡果不足惜可免,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望做粤。 院中可真熱鬧浇借,春花似錦、人聲如沸怕品。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肉康。三九已至闯估,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吼和,已是汗流浹背睬愤。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留纹安,地道東北人尤辱。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像厢岂,于是被迫代替她去往敵國和親光督。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容