概述
使用 vue-cli 工具生成一個 vue 項目:
vue init webpack my-project-vue
在生成的項目結構里,會有一個 index.js 文件。在這個文件里,會有一個 proxyTable 的空節點.
理解這個節點的作用需要有兩個前置知識:
- 前端跨域
- 利用代理服務器進行跨域
proxyTable
proxyTable 是 vue-cli 腳手架在開發模式下,引用了 webpack-dev-server 工具,它為本地開發提供了一個用來跨域的代理中轉服務器服務,基於它引用的中間件 http-proxy-middleware 提供了跨域服務。
為什么要用 proxyTable ?
在開發期間與我們協作的后端開發可能沒有給自己的服務 (接口) 提供 CORS 跨域服務,而瀏覽器存在同源策略,我們通過超文本語言在瀏覽器發出的 httpRequest 會被該策略攔截服務響應。而服務器是不存在這一策略的,所以才存在防火牆這一工具,協同后端開發一起關閉防火牆* 以后通過代理服務器中轉對方本地的接口服務到代理服務器監聽的本地端口,以此便可以實現跨域請求服務。以下簡單舉出幾個需要跨域的例子:
- 端口不同(同一設備啟動不同服務):前端192.168.0.1:1111 - 服務192.168.0.1:2222
- 網段不同(同一局域網內不同設備):前端192.168.0.1 - 服務192.168.0.2
- 內網不同(不同局域網的不同設備):前端192.168.0.1 - 服務192.168.1.1
- 網絡不同(交換機分配的局域網通過共用的公網IP請求廣域網):前端192.168.0.1 - 服務218.1.1.1
需要跨域的應用場景基本都含括在以上情況中。
如上圖,由於瀏覽器的同源策略我們無法通過 httpRequest 跨域請求服務,瀏覽器截獲了這次服務的響應,沒有返回給頁面。
解決的辦法有三個:
- 協商后端開發人員為他本地的接口開啟 CORS 服務。
- 通過代理服務器中轉請求,vue請求的仍然是自己的后台,再由沒有同源策略的代理后台去請求真正的后台,再由代理后台將數據返回給vue,這里的代理后台可由 proxyTable 、 Nginx 等工具或插件提供 。
- 通過JSONP進行跨域,如我們在一個簡單的html頁面中引入 jQuery 或 BootStrap 等外部包時,只需要通過 script 標簽引入目標源路徑即可,可以看出這種方式是不存在同源策略的,我的另一篇文章API:獲取當前用戶的公網IP就是通過JSONP的方法訪問到第三方在公網上提供的API並返回了數據。
訪問一個不支持跨域的后台服務接口
這里用 node.js 寫一個簡單的http服務,端口號為54321,服務會返回一個 json 數據,但並不提供跨域功能。
const http = require('http') const fs = require('fs') http.createServer((request, response) => { console.log(request.url) // 對於所有請求,都返回這個json數據. fs.readFile('./json.data.json', 'utf-8', (err, data) => { response.end(data) }) }).listen(54321, () => { console.log(`server is running at 54321`) })
通過ip直接訪問測試:
接着通過 vue-cli 創建一個服務端口為8080的 vue 項目后,在 App.vue 里修改代碼:
created() { this.axios.get('http://localhost:54321/json.data.json') .then(response => { this.users = response.data.todoList console.log(this.users.todoList) }) .catch(error => { console.log(error) }) },
不出意外提示跨域了 (vue:8080) & (json.data:54321)
假設這個后台是后端開發寫的,在一個公司只有零星幾個項目的情況下,並且有多位前端同時,可以協商后端開發為接口提供跨域服務。
但如果公司有很多個項目,或是離職的人 / 其他公司的人寫的,我們無法協商讓他們為服務提供 CORS 來支持跨域,那么就理應我們對項目配置跨域來進行開發和維護。
配置proxyTable進行跨域
proxyTable 跨域的基本原理是:
在開發模式下, webpack 會為我們提供一個 http 代理服務器.
我們請求接口的時候,實際上是請求的 webpack 提供的這個 http 代理服務器.
再由這個代理服務器請求真正的接口服務器.
最后數據經由 webpack 代理服務器,最后轉交給我們的 vue 程序.
為什么在流程中加一個代理服務器就可以了?
如上文所說,服務器不同於瀏覽器,沒有同源安全策略的限制。了解了跨域的基本原理,接着配置 proxyTable 節點的配置屬性。
proxyTable: { // 這里配置 '/api' 就等價於 target , 我們在鏈接里訪問 /api === http://localhost:54321
// 代理需要一個標識,告訴代理服務器某個路徑需要代理,否則可能項目的 html、css、js 這些靜態資源也會從目標服務器代理到本地服務
// '/api': {} 中的 /api 可以理解為全局關鍵字,表示target下的所有接口需要代理服務器中轉,如果是 /apis ,則表示以 /apis 開頭的接口
'/api': { target: 'http://localhost:54321/', // 我們要請求的目標服務器 secure: true, // 如果是 https ,需要開啟這個選項. changeOrigin: true, // 是否是跨域請求. pathRewirte: { // 這里是追加鏈接,英文直譯過來就是它的作用:路徑重寫、重定向.
// 如果沒有重定向我們訪問的將是: 'http://localhost:54321/api/json.data.json
// 將 /api 重寫為空字符串 我們就能請求到正確路徑: 'http://localhost:54321/json.data.json'
'^/api': '', } } },
該功能由 http-proxy-middleware 提供,詳細的 proxyTable 配置請查看官方文獻http-proxy-middleware.
配置Nginx進行跨域
Nginx 作為一個高性能的 HTTP 和 反向代理 的web服務器,因它的穩定性、豐富的功能集、簡單的配置文件和低系統資源的消耗而聞名。
同時它非常的輕量級,其特點是占有內存少,並發能力強,在中國大陸使用 Nginx 的網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等,可見其穩定和性能有多強大。
Nginx 由於應用場景多存在於服務器,一般為后端開發人員熟知,但其 反向代理 功能也可以使本地頁面實現跨域,也因此被前端開發人員熟知。
前端配置跨域操作可通過我的另一篇文章 Nginx:多項目開發配置跨域代理 查看,該文詳細介紹了整個配置的操作,非常的簡單快捷。