「前端必看」這篇Nginx反向代理技巧,助你準時下班陪女神

最近同事小G老是悶悶不樂,讓我感受慌慌的,難道是我平時壓榨小G了?我轉念一想,不該該啊,工做量事先都評估好了,沒道理每天加班啊。html

坐下來聊聊後,小G向我吐槽說,」改bug效率過低了,天天加班改bug,都不能早點下班陪女神!」前端

我深吸一口氣,「臥槽,忘記傳授小G祕籍了...」linux

在一步步提問引導下,我搞清楚了小G的問題所在......webpack

改bug好慢
改bug好慢
切生產環境調試還要重跑服務
切生產環境調試還要重跑服務
我只想訪問不一樣環境
我只想訪問不一樣環境
代理層須要解耦
代理層須要解耦

問題引入

相信不少前端朋友在線上debug時都吐槽過npm run devnpm start太費時的問題吧(這裏提到的兩條npm腳本代指啓動前端dev server)。nginx

因爲環境差別,開發環境和生產環境下,咱們訪問的後端服務域名是不同的。那麼當咱們debug生產問題時,不免仍是要修改下webpack devServerproxy配置指向生產環境域名,而後重啓devServer,這個過程通常比較緩慢。web

有些時候可能測試環境也能復現bug,那麼只要接入測試環境也能排查問題緣由。但這不是本文關注的重點,本文主要說說如何提升debug效率。npm

webpack-dev-server反向代理

0202年了,若是做爲開發者的你還不瞭解反向代理,那麼是頗有必要去關注下了。windows

咱們知道,跨域對於前端而言是一個沒法逃避的問題。若是不想在開發時麻煩後端同事,前端仔必須經過本身的手段解決跨域問題。固然,你幫後端同事買包辣條,他給你經過CORS解決跨域也是能夠的。後端

還好,webpack-dev-server幫咱們解決了這個痛點,它基於Node代理中間件http-proxy-middleware實現。api

配置起來也很是簡單:

proxy: {
 // 須要代理的url規則  "/api": {  target: "https://dev.xxx.tech", // 反向代理的目標服務  changeOrigin: true, // 開啓後會虛擬一個請求頭Origin  pathRewrite: {  "^/api": "" // 重寫url,通常都用獲得  }  } } 複製代碼

這個時候小G打斷了我,表示不理解。

說了半天還不懂
說了半天還不懂

反向代理是個什麼意思呢?舉個例子,我想找馬雲借錢,馬雲是確定不會借給個人。

馬雲對錢沒興趣
馬雲對錢沒興趣

可是我有一個好朋友老張,我因而找老張借了1W塊,可是我沒想到這個朋友和馬雲關係不錯,他從馬雲那裏借了1W塊,而後轉給我。也就是說,我不知道我借到的錢實際來源於哪裏,我只知道我從我朋友老張那裏借到了錢,老張給我作了一層反向代理。

具體到開發中就是,我前端仔要從https://dev.xxx.tech這個域名調用後端接口,可是我前端開發服務運行在http://localhost:8080,直接調用後端接口會跨域,被瀏覽器同源策略阻塞,因此這條路是走不通的。

所以我須要從前端服務器作個代理,這樣我就能夠用http://localhost:8080/api/user/login這種形式調用接口,就好像在調前端本身的接口同樣(由於我訪問的是前端的url嘛)。

然而其實是前端服務器作了一層代理,把http://localhost:8080/api/user/login這個接口代理到https://dev.xxx.tech/user/login。這對前端開發者而言是無感的。

代理層模型
代理層模型

簡單總結就是:反向代理隱藏了真實的服務端;相反地,正向代理隱藏了真實的客戶端,相似kexueshangwang這種。

debug痛點

問題來了,假設咱們正在feature分支開發需求,這個時候上頭通知要即時排查和解決一個生產bug,假設生產環境域名爲https://production.xxx.tech

咱們通常會stash代碼,而後切fix分支,修改target的值爲"https://production.xxx.tech",而後從新運行npm start重啓開發服務器接入生產環境,靜靜等待,放空本身......

放空本身
放空本身

這個時候咱們就會幻想「唉,要是不用等這麼久就行了!」

是的,其實不少時候,一個bug並不複雜,可能解決bug只要1分鐘,然而咱們切換環境從新運行開發服務器就花了1分鐘(大多數狀況可能超過這個時間)。那麼如何解決這個問題?

代理層解耦

是的,有的同窗已經想到了,只要把代理服務器抽離出來,問題即可以獲得解決,我再也不須要把前端編譯過程和服務代理目標捆綁在一塊兒。在生產環境,這種Nginx轉發對大多數人而言早已經是熟門熟路,然而不多有人會嘗試在開發環境中也這麼作。那麼不妨這樣試試呢!

下載Nginx

咱們照常下載Nginx,選擇Windows穩定版便可。

固定前端代理

爲了不在debug線上問題時須要切換proxy target而從新運行npm start,咱們在前端層把proxy target固定下來。好比我固定訪問127.0.0.1:8090(固然,實際上訪問哪一個端口能夠視我的狀況調整)。

proxy: {
 "/api": {  target: "127.0.0.1:8090", // 固定代理目標  changeOrigin: true,  pathRewrite: {  "^/api": ""  }  } } 複製代碼

而後從127.0.0.1:8090確定是沒法訪問到後端接口的,請接着往下看!

Nginx代理

因爲前端的接口訪問已經固定爲127.0.0.1:8090,那麼剩下的工做就交給Nginx吧。咱們只要在Nginx中監聽本地8090端口,把請求通通轉發給目標服務器便可,配置以下:

server {
 listen 8090;  server_name 127.0.0.1;   location / {  proxy_pass https://dev.xxx.tech;  proxy_http_version 1.1;  proxy_set_header Upgrade $http_upgrade;  proxy_set_header Connection "upgrade";  proxy_set_header Host $host;  # proxy_set_header X-Real-IP $remote_addr;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  } } 複製代碼

能夠看到,我在配置中註釋了X-Real-IP,而咱們在生產環境下配置Nginx時,通常會保留這幾項Host,X-Real-IP,X-Forwarded-For,用以保留請求的服務器域名,原始客戶端和代理服務器的IP等信息。

若是不註釋X-Real-IP,前端訪問入口的真實IP是127.0.0.1localhost,Nginx不承認這樣的本地ip,直接返回404,客戶端請求不予代理到其餘遠程服務器。不扯了,這裏具體的緣由我也不知,若有大佬知道緣由,還請點撥下,太感謝了。

好了,回到正題,有了以上的配置,咱們就能夠將前端代理層和Nginx代理層解耦,前端固定經過本地127.0.0.1:8090訪問後端接口,而具體接口是代理到開發環境、測試環境或是生產環境,由Nginx決定,只須要修改nginx.conf後重啓便可。

而Nginx熱重啓是很是快的,一條命令便可實現,幾乎零等待時間。

// windows下是這個命令
nginx.exe -s reload // linux是這樣的 nginx -s reload 複製代碼

本地域名

聽到這裏,小G又將了我一軍。

端口占用
端口占用

還好我早有準備,沒有自亂陣腳。

若是真的遇到本地端口被佔用的狀況,最簡單的辦法固然是換個端口。

爲了杜絕這種狀況,咱們能夠引入本地域名,兼具「裝逼」效果。

咱們知道,域名是經過解析後才能獲得真實的服務IP。而域名解析過程當中也有這麼一些關鍵節點,是咱們應該知道的。

  • 瀏覽器緩存
  • 操做系統hosts文件
  • Local DNS
  • Root DNS
  • gTLD Server

借用網上一張圖說明下大體流程(侵刪)。

域名解析過程
域名解析過程

上圖沒提到hosts文件,可是不影響咱們魔改。咱們只要在操做系統hosts文件這個節點動下手腳,就能夠實現本地域名了。

首先,咱們找到C:\Windows\System32\drivers\etc\hosts這個文件,打開後在最後新增一條解析記錄

127.0.0.1 www.devtest.com
複製代碼

而後保存這個文件,保存hosts文件時須要administrator權限。

這就至關於告訴本地操做系統,若是用戶訪問www.devtest.com,我就給他解析到127.0.0.1這個ip

因此,咱們在Nginx只要監聽127.0.0.180端口便可,配置以下。

server {
 listen 80;  server_name 127.0.0.1;   location / {  proxy_pass https://dev.xxx.tech;  proxy_http_version 1.1;  proxy_set_header Upgrade $http_upgrade;  proxy_set_header Connection "upgrade";  proxy_set_header Host $host;  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  } } 複製代碼

最後,咱們只要在前端工程中把代理目標設置爲www.devtest.com便可。

proxy: {
 "/api": {  target: "http://www.devtest.com", // 固定代理目標  changeOrigin: true,  pathRewrite: {  "^/api": ""  }  } } 複製代碼

這樣前端訪問的某接口http://localhost:8080/api/user/login就會被代理到http://www.devtest.com/user/login,而www.devtest.com被本地hosts文件解析到127.0.0.1,接着Nginx監聽了127.0.0.180端口,將請求轉發到真實的後端服務,完美!

對了,www.devtest.com是我特地命名的一個沒法訪問的域名,因此你千萬別把www.taobao.com這種地址解析到本地哦,否則你無法給女神買禮物別怪我。。。

準時下班
準時下班

今天分享給你們的乾貨就這麼多,祝願你們準點下班陪女神!

看到最後,求個關注點贊,歡迎你們加我微信交流技術,閒聊也能夠哦!

關注交流
關注交流

本文使用 mdnice 靈動藍主題 排版

相關文章
相關標籤/搜索