在前端開發過程中,你可能經常會遇到一個頭疼的問題:當你在本地啟動的前端項目中調用后端接口時,瀏覽器控制臺會報出類似 “Access to fetch at ‘http://xxx’ from origin ‘http://localhost:3000’ has been blocked by CORS policy” 的錯誤。這就是跨域問題,而 Vite 的代理功能正是解決開發階段跨域問題的有效方案。
讓我們從一段常見的 vite.config.ts 配置代碼說起,看看其中的代理設置到底是如何工作的。
在 Vite 的配置文件中,server 選項用于配置開發服務器的行為,其中的 proxy 屬性就是專門用來設置代理規則的。比如這樣的配置:
server: {host: "0.0.0.0", // 默認為localhostport: 7001, // 端口號open: false, // 是否自動打開瀏覽器proxy: {// 第三方服務器的代理配置'/dev-api/PileManager': {target: 'http://personalpile.admin.usteu.com/',changeOrigin: true,rewrite: (path) => path.replace(/^\/dev-api/, '')},// 本地后端服務的代理配置"/dev-api": {target: "http://localhost:8050/",changeOrigin: true,rewrite: path => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '/api')}},
}
首先我們要理解,為什么需要代理。當你的前端項目運行在http://localhost:7001(由 port 指定),而后端接口部署在另一個域名或端口(比如http://localhost:8050)時,由于瀏覽器的同源策略限制,直接請求會被攔截。代理的作用就是讓前端請求先發送到本地的 Vite 開發服務器,再由 Vite 服務器轉發到目標后端服務器,這樣就避開了瀏覽器的跨域限制。
我們來看 proxy 對象中的具體配置。這里定義了兩組代理規則,每組規則都是一個鍵值對。鍵表示需要被代理的請求路徑前綴,而值則是該前綴對應的代理配置。
先看第一個代理規則’/dev-api/PileManager’。當你的代碼中發起類似fetch(‘/dev-api/PileManager/some/path’)的請求時,Vite 會攔截這個請求,并按照配置進行處理。target 指定了目標服務器的地址,這里是http://personalpile.admin.usteu.com/,意味著這個請求會被轉發到該服務器。
changeOrigin 設置為 true 是一個很重要的配置,它表示在發送請求到目標服務器時,會修改請求頭中的 Origin 字段,讓目標服務器以為請求來自于它自己所在的域,從而避免一些服務器可能存在的域名驗證限制。
rewrite 則用于修改請求路徑。這里的path.replace(/^/dev-api/, ‘’)表示會把請求路徑中開頭的/dev-api去掉。原來的請求路徑是/dev-api/PileManager/some/path,經過重寫后就變成了/PileManager/some/path,然后再拼接上 target 的地址,最終請求的實際地址就是http://personalpile.admin.usteu.com/PileManager/some/path。
再看第二個代理規則"/dev-api"。這里你可能會疑惑,它的路徑前綴看起來和第一個規則有重疊,為什么能正常工作?這是因為 Vite 在匹配代理規則時,會優先選擇更具體、更長的路徑前綴。只有當請求路徑不匹配第一個規則時,才會匹配這個更通用的規則。
這個規則的 target 設置為本地的http://localhost:8050/,通常這是開發者自己的后端服務。rewrite 這里使用了env.VITE_APP_BASE_API,這是一個從環境變量中獲取的值,通常也是/dev-api。所以這個重寫規則的意思是,把請求路徑中開頭的/dev-api替換成/api。比如原來的請求是/dev-api/user/list,重寫后就變成了/api/user/list,最終請求的實際地址是http://localhost:8050/api/user/list。
通過這樣的代理配置,前端開發者就不需要在代碼中硬編碼不同環境的接口地址,也不需要擔心開發階段的跨域問題。Vite 會自動幫我們完成請求的轉發和路徑的處理,讓我們可以專注于業務邏輯的開發。
需要注意的是,這些代理配置只在開發階段生效,因為它是 Vite 開發服務器提供的功能。當項目打包上線到生產環境時,通常會使用 Nginx 等服務器來配置類似的反向代理功能,以確保生產環境中的接口請求也能正常工作。
那么nginx大概應該怎么配置呢,如下示例:
location /dev-api/PileManager/ {proxy_pass http://personalpile.admin.usteu.com/PileManager/;proxy_set_header Host personalpile.admin.usteu.com;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;
}location /dev-api/ {proxy_pass http://127.0.0.1:8050/api/;# 連接增強配置client_max_body_size 1000m;send_timeout 3600s;keepalive_timeout 3600s; # 保持連接活性(網頁7補充)keepalive_requests 10000; # 單連接最大請求數# SSE核心配置proxy_http_version 1.1; # 強制使用HTTP/1.1協議(網頁1、網頁6)proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";#關閉代理緩沖,確保實時傳輸proxy_buffering off;proxy_cache off; # 關閉緩存防止數據截斷proxy_read_timeout 86400s; # 24小時超時(網頁1建議值)proxy_set_header Cache-Control 'no-cache';add_header Cache-Control no-cache;# 頭信息增強proxy_set_header X-Accel-Buffering no;# 下面三句話是用來獲取用戶訪問的ip的proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Last-Event-ID $http_last_event_id;# CORS跨域支持(網頁3、網頁5)add_header 'Access-Control-Allow-Origin' $http_origin always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Content-Type,Authorization,Last-Event-ID' always;add_header 'Access-Control-Expose-Headers' 'Content-Type,Content-Length' always;# 預檢請求處理(網頁2、網頁6)if ($request_method = OPTIONS) {add_header 'Access-Control-Max-Age' 1728000;add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Last-Event-ID';add_header 'Content-Type' 'text/plain; charset=utf-8';return 204;}
}
以上展示了當我們的前端需要調用其他第三方服務器的接口時,我們在本地開發環境和線上生產環境分別需要做的事,筆者展示了詳細的代理示例,希望給大家帶來參考價值。