本文適用人羣:javascript
問題導向前端
平常開發中,前端常常須要經過 ajax 從後端獲取數據。而在這種先後端分離的開發模式下,每每前端項目與後端項目的 IP地址、端口號、協議 大機率是不同的,因爲瀏覽器的安全策略設定,不進行相應配置的話,前端的請求就會被瀏覽器攔截掉啦。vue
假設某個頁面組件在加載的時候會向後端發送一個請求,而後根據返回的結果來渲染頁面。代碼示例以下:java
前端項目經過 npm run dev
運行在 localhost:8081 上,webpack
後端項目經過 apache 運行在 localhost/test/public/api/books
上ios
<template> <div class="hello"> <ul> <li v-for="book of books">{{book.name}}</li> </ul> </div> </template> <script> import axios from 'axios'; export default { name: 'HelloWorld', data() { return { books: [] } }, created(){ let self = this; axios.get("http://localhost/test/public/api/books") .then((response)=>{ self.books = response.data; }); } } </script>
直接訪問後端連接,將能獲得如下返回內容:git
[ {"name":"javascript \u4ece\u5165\u95e8\u5230\u653e\u5f03"}, {"name":"\u9888\u690e\u75c5\u5eb7\u590d\u6307\u5357"}, {"name":"\u89c6\u529b\u4fdd\u62a4\u6307\u5357"} ]
可是當咱們在瀏覽器中運行前端頁面,會報錯!控制檯打印以下:github
可見,瀏覽器對於跨域訪問進行了限制,由於在例子中前端項目url與後端項目url的端口號不相同,因此瀏覽器攔截了咱們的請求。web
解決方案ajax
解決方式有不少種,包括能夠很簡單粗暴地讓後端代碼設置一個 Access-Control-Allow-Origin 頭來解決這個問題。可是,在實際開發中,後端的小哥哥們纔不會理會你這個羞恥的小請求呢~
那怎麼辦咧~
其實咱們能夠經過配置 vue 項目中的 config/index.js 來解決問題。
將 dev 中的 proxyTable 改成以下:
proxyTable: { '/api': { target: 'http://localhost/test/public/api/', changeOrigin: true, pathRewrite: { '^/api': '' } } },
接着,再將 vue 組件頁面中的 ajax 請求代碼改成以下:
// 改成這樣,原來是這樣:axios.get("http://localhost/test/public/api/books") axios.get("/api/books")
從新運行 npm run dev ,運行效果以下:
爲何這麼作?
當咱們打開瀏覽器的開發者工具查看一下網絡請求就會發現,這個 ajax 請求居然是向咱們前端的 webpack-dev-server 發送的:
並且竟然能返回正確的數據???
瀏覽器有安全策略限制,可是第三方的服務(服務器)沒有呀,因此咱們能夠經過讓瀏覽器訪問前端開發服務器的url,讓前端開發服務器去向後端服務器發送請求,再返回數據給瀏覽器,這樣子就不存在跨域問題啦。
當咱們在配置中這麼寫時:
proxyTable: { '/api': { target: 'http://localhost/test/public/api/', } },
對於8081端口的開發服務器而言,全部以 /api 開頭的 uri 都會被轉發到 http://localhost/test/public/api/ ,
也就是說,在瀏覽器中訪問 localhost:8081/api/books ,前端開發服務器就會向 http://localhost/test/public/api/api/books 請求數據。就是簡單粗暴地在 target 以後拼接上當前的uri。
會發現這樣子作,實際的 url 中多了一個 /api ,不知足咱們的需求,因此能夠經過 pathRewrite 將這幾個字符串替換掉。
// 將 "/api" 開頭的 url 中的 "api" 替換成 空 proxyTable: { '/api': { target: 'http://localhost/test/public/api/', pathRewrite: { '^/api': '' } } }, // 根據上面的規則 // 當在瀏覽器訪問 localhost:8081/api/books // 則實際訪問的是 http://localhost/test/public/api/books // 假設設置成 pathRewrite: {'^/api': '/somethingnew'} // 當在瀏覽器訪問 localhost:8081/api/books // 則實際訪問的是 http://localhost/test/public/somethingnew/books
而配置項 changeOrigin: true 則是設置了前端開發服務器向後端發送請求時 HTTP 包中的 HOST 字段。當設置爲 true 時,HOST 會被設置成目標地址(target)中的主機。當後端服務器是虛擬主機時,這個選項顯得尤其重要,或者說,同一個IP綁定了多個服務器服務時顯得尤其重要。不設置的話,可能會致使請求不到數據。
更多的 proxyTable 可用參數能夠參考 http-proxy-middleware 的文檔