概述
使用 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:多项目开发配置跨域代理 查看,该文详细介绍了整个配置的操作,非常的简单快捷。