Vue CLI4.0 webpack設定屬性——devServer.proxy

2020-09-28 11:00:48

前言

《Vue CLI4.0 webpack設定屬性——devServer》中,我初略提及了 devServer.proxy 。但是並沒有做詳細的講解。一、是因為,面對跨域問題,我常用的做法是讓後端做處理;第二個原因呢?其實我並沒有真正的設定成功過。所以我不敢寫,怕誤導大家。

關於後端如何處理跨域問題,可檢視:《koa2 + VueCLI 4.0 + axios 跨域問題》

devServer.proxy

devServer.proxy

  • Type: object [object, function]

  • 作用: 設定API存取代理。如果你有單獨的後端開發伺服器 API,並且希望在同域名下傳送 API 請求 ,那麼代理某些 URL 會很有用。

  • 用法

    module.exports = {
      proxy: {
            '/api': {
            target: 'http://127.0.0.10:3000'
         }
      }
    };
    

常用 options (屬性)

  • targe

    • Type: string

    • 作用:代理的伺服器,也就是api要存取的伺服器。

    • 用法:

      module.exports = {
        proxy: {
              '/api': {
              target: 'http://127.0.0.10:3000'
           }
        }
      };
      
  • ws

    • Type: boolean

    • 作用:是否代理websocket

    • 用法:

      module.exports = {
        proxy: {
              '/api': {
              target: 'http://127.0.0.10:3000',
              ws: true
           }
        }
      };
      
  • secure

    • Type: boolean

    • 作用:是否使用HTTPS協定。預設,false。

    • 用法:

      module.exports = {
        proxy: {
              '/api': {
              target: 'http://127.0.0.10:3000',
              secure: true
           }
        }
      };
      
  • changeOrigin

    • Type: boolean

    • 作用: 將主機頭的來源更改為目標URL,也就是是否允許跨域

    • 用法:

      module.exports = {
        proxy: {
              '/api': {
              target: 'http://127.0.0.10:3000',
              changeOrigin: true
           }
        }
      };
      
  • pathRewrite

    • Type: object

    • 作用:重寫 url 的 path 部分。

    • 用法:

      module.exports = {
        proxy: {
              '/api': {
              target: 'http://127.0.0.10:3000',
              pathRewrite: {"^/api" : ""}
           }
        }
      };
      

擴充套件:devServer.proxy 的詳細說明

一、url 中的path 是什麼?

假設我們有這樣一個url: https://github.com/chimurai/http-proxy-middleware

path是上面那一部分呢?

首先,我要明確一點。這裡的path不等於url,它是url中的一部分。這可能是很多人理解錯的地方。

請看下圖:

  foo://example.com:8042/over/there?name=ferret#nose
  \_/   \______________/\_________/ \_________/ \__/
   |           |            |            |        |
scheme     authority       path        query   fragment

這是《http-proxy-middleware》官方檔案給出來的圖。上面標示了一個url的結構。、

各個部分說明如下:

  • scheme: 請求協定
  • authority: 域名
  • path: api 的路徑
  • query: 請求引數
  • fragment: 錨點, 次級資源定位符

類比快遞:

scheme 就是派送的快遞;authority + path 則組成快遞地址,authority 是個大致地址,就好比快遞地址的城市,而 path 就是地址中城市後面的詳細地址了;query就是快遞本身;而fragment則是快遞單的備註或者是快遞的說明書。

當然了,上面的比喻可能不恰當啦!

關於這部分的更詳細的講解,可檢視:《URI’s fragment》

二、devServer.proxy 的工作原理

proxy 接受一個物件,物件鍵值對的 key 用來匹配 api 的 url 中的 path。也就是說,當我們進行如下設定時:

module.exports = {
  proxy: {
        '/api': {
        target: 'http://127.0.0.10:3000',
     }
  }
};

devServer 會自動對 path 為 /api 開頭的 api 做代理轉發。而 path 不是 /api 開頭的就不會進行處理。

注意:

需要注意一點,devServer 預設傳遞過來的 api url 是不包含 scheme 和 authority 的。換而言之,devServer 會從傳遞過來的 api url 的第一個字元進行匹配。如果你給api url 補上了 scheme 和 authority 的(如:http://127.0.0.10:3000/api/getData),它是不匹配的,因為開頭是http

所以如果我們需要使用 devServer.proxy 。那就一定不能設定 axios 的 baseURL,或者把baseURL設為空字串

三、pathRewrite 屬性講解

pathRewrite 接受一個物件。

  • key: 物件鍵值對中的 key 是一個正規表示式。這裡需要注意正則的寫法,必須與^開頭。熟悉正規表示式的朋友就會知道,這表明,傳給 deveServer.proxy 的 api 的 url 必須是以正規表示式所要匹配的字串開頭。

    例如:

    我們做了如下設定

    pathRewrite: {"^/api" : ""}
    

    現在這樣兩個 api:

    1. http://localhost:80/api/login
    2. /api/login

    devServe.proxy 匹配哪個?

    會匹配第二個,因為第二個以/api開頭,而第一個以http開頭。

  • value: 物件鍵的 value 是個字串,用來替換 key 匹配的字串。

四、pathRewrite 替換的結果

有了上面的知識,那我們就可以明白 pathRewrite 的工作原理以及結果是什麼。

例如:

有這樣的 api:/getUserInfo,其所在的伺服器為http://192.168.0.169。那這個 api 的url 就應該是http://192.168.0.169/getUserInfo

然後在 axios 設定的 route 是 /api/getUserinfo

那為了能正常存取。就需要做如下設定:

module.exports = {
  proxy: {
        '/api': {
        target: 'http://192.168.0.169',
        pathRewrite: {"^/api" : ""}
     }
  }
};

這樣設定之後,devServer.proxy 就能把 url 改寫成http://192.168.0.169/getUserInfo

關於devServer.proxy 更詳細的用法可查閱:《vue-cli 3.0之跨域請求devServer代理設定》

proxy的簡寫

在閱讀 Vue 官方檔案說明時,你可能會看見這樣的寫法:

module.exports = {
  devServer: {
    proxy: 'http://localhost:4000'
  }
}

上面其實是一種簡寫。等同於:

module.exports = {
  proxy: {
        '/api': {
        target: 'http://localhost:4000'
     }
  }
};

這部分的解釋可以再http-proxy-middleware外掛的說明檔案中看到。地址如下:https://github.com/chimurai/http-proxy-middleware

參考文章

vue-cli 3.0之跨域請求devServer代理設定
vue-cli 設定參考
http-proxy-middleware
devserver-proxy
URI's fragment

文章跳轉