一文理清環境變數的使用與代理的管理

致爱丽丝發表於2024-09-26

早在2020年就想寫一篇類似的總結,但一直想的到沒做到

這兩天又遇到了此類問題,索性直接來一篇

專案裡有envenv.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是一個比較大的條件檔案

以上。

相關文章