早在2020年就想寫一篇類似的總結,但一直想的到沒做到
這兩天又遇到了此類問題,索性直接來一篇
專案裡有env
、env.devlopment
env.prodction
等等檔案,此類.env開頭的檔案統稱為開發環境配置檔案,目的是什麼?目的是為了基於啟動時所選擇的環境來配置不同的地址或者資料(是的就是你心中所想的在package.json中配置的script項)
.env
優先順序小於所有env.xxx
檔案,也就是說在找不到所有類似檔案的情況下.env會被最終解析
在vite專案中,可以控制檯輸出 import.meta.env
來獲知當前所處的環境,webpack中其實也差不多,輸出的語句不同罷了。
如何區分開發或者生產
專案執行執行本地伺服器localhost
是在本地 npm run xxx
專案執行構建命令是線上上npm build xxx
env與proxy的關係:
舉個例子
專案中,有時候要連線幾個不常用的介面
假設我需要在專案中訪問一個與後端不同的的介面,本質上是將跨域介面偽裝成了本地介面以規避瀏覽器跨域問題, 它的地址可能是這樣:http://www.wzdxcsk2.com/xxxx/yy
如何在專案中訪問這個介面?它作為一個額外的介面,並不與後端介面一致
專案分為線上版與開發版本(萬變不離其宗)兩種。
為了保證我們可以在開發環境可以正確呼叫api,
腳手架通常會提供一個proxy物件,用以暫時遮蔽瀏覽器端的跨域問題
一個最簡單的proxy:
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path: string) => path.replace(new RegExp(`^/api`), ''),
}
它的意思是說,如果遇到一個/api作為字首的api介面,就將其轉換為target指定的地址,
如:發出的請求應該是"http://jsonplaceholder.typicode.com/sayhi ",而在定義介面的時候應該用"/api/sayhi",這樣腳手架在捕獲到這個介面時,就會將其轉換成"localhost:port/api/sayhi",但只是偽裝,本質上也只是為了欺騙
瀏覽器的跨域機制用於開發
線上環境若需要訪問不屬於後端的介面,則需要介面提供方提供跨域支援,因為前端線上上其實也僅僅是一個個靜態資源,這時候就得需要介面服務端在他們的程式碼中允許訪問跨域請求
BOOM
有了這麼多前置知識,接下來就可以理清環境變數與env在日常環境中的配合使用了
假設有這樣一個外來介面http://jsonplaceholder.typicode.com/define/problem
需要呼叫,
在此可以提供一個基礎正規化:不保證完全優雅,但保證可用
前面說過了env開發與線上的區別,對此,我們可以分別在env的不同環境配置相同的資料:
# env開發環境下:
# env.development
VITE_API_URL_PREFIX_YY=/WZDXCSK
# env生產環境下:
# env.produect
VITE_API_URL_PREFIX_YY=http://jsonplaceholder.typicode.com
而我們在定義介面時,則需要使用import.meta.env.VITE_API_URL_PREFIX_YY
來確定此刻的介面究竟是什麼,如果以上述配置來看,假設fetch介面為http://jsonplaceholder.typicode.com/define/problem
則開發時import.meta.env.VITE_API_URL_PREFIX_YY + '/define/problem'
url為:/WZDXCSK/define/problem
則生產時import.meta.env.VITE_API_URL_PREFIX_YY + '/define/problem'
url為:http://jsonplaceholder.typicode.com/define/problem
是的也許會很疑惑:開發時的介面全路徑為/WZDXCSK/define/problem
,這並不是一個完整的合法的api,是的,但是由於是在開發環境,而我們則可以使用腳手架下的proxy來規避這個問題:
//腳手架的配置檔案 config.js
proxy:{
//以上述為例,開發環境下import.meta.env.VITE_API_URL_PREFIX_YY被統一替換成了/WZDXCSK,那麼我們直接對其代理轉換即可
'/WZDXCSK':{
target:'http://jsonplaceholder.typicode.com' //將指定的字首替換成真正的api介面
rewrite: (path: string) => path.replace(new RegExp(`^/WZDXCSK`), ''), // 將匹配完畢後將原本的替換成空,因為'/WZDXCSK'是我們臆想出來的
changeOrigin: true,// 是否跨域
}
}
值得一提的是,proxy只允許開發環境下使用,這是為了方便開發者,而在生產環境下則需要後端開發者配置允許跨域,
換句話說,開發環境下的跨域FE可以自己解決,線上環境下的跨域則需要BE處理:
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
👆:生產環境下以上報錯須後端解決。
總結一下:
透過使用env檔案我們可以自由定義api地址。其實我們可以定義的還有很多,總而言之,env是一個比較大的條件檔案
以上。