一、为啥Vue2项目需要proxy?
做Vue2项目开发时,有没有碰到过“跨域请求被浏览器拦截”的情况?比如调后端接口时,控制台报错“Access to XMLHttpRequest at xxx from origin xxx has been blocked by CORS policy”,这时候很多人会听说用proxy解决,可proxy到底是干啥的?配置起来难不难?实际开发咋用?今天咱就把Vue2里的proxy掰开揉碎讲清楚,从原理到配置再到踩坑,一次性搞懂~
先搞明白“跨域”是咋回事,浏览器有个「同源策略」,只有协议、域名、端口全一样的请求才算“同源”,不同源的请求会被拦截,比如前端开发时,本地启动的服务是http://localhost:8080
,而后端接口域名是 https://api.example.com
,协议、域名都不一样,这就触发跨域了。
那开发阶段咋解决跨域?常见方案有三种:
- 后端开CORS:后端在响应头加
Access-Control-Allow-Origin
等字段,允许前端域名访问,但开发时可能后端还没配,或者想自己控制,不够灵活。 - JSONP:利用
script
标签不受同源策略限制的特点,但只能发GET
请求,还得后端配合返回特定格式(比如用回调函数包裹数据),局限性很大。 - proxy代理:这是前端在开发阶段最常用的方式!原理是借助
webpack-dev-server
(Vue2项目默认用webpack打包,开发时启动的本地服务)做“中间人”:前端请求先发给本地devServer,devServer再把请求转发到后端域名,因为浏览器只和本地devServer通信(同源),devServer和后端通信(服务器之间请求没浏览器限制),所以绕开了跨域限制。
proxy在Vue2里咋配置?
Vue2项目的配置文件是 vue.config.js
(如果没有就新建),重点看 devServer.proxy
这个配置项,下面一步步拆解配置逻辑,再举个实战例子~
核心配置项解释
配置 proxy 时,主要关注这几个属性:
target
:要代理到的后端域名(必须带协议,http://
或https://
)。changeOrigin
:是否修改请求头里的origin
,设为true
后,后端会以为请求是从自己的域名发过来的(否则后端可能识别出是前端代理的,导致权限拦截)。pathRewrite
:路径重写,前端请求带的前缀(/api
),后端接口可能没有这个前缀,所以要把前缀替换掉。
实战配置案例
假设后端接口域名是 https://api.example.com
,前端所有以 /api
开头的请求都要代理到这里,配置代码如下:
module.exports = { devServer: { proxy: { '/api': { // 匹配请求路径中以“/api”开头的请求 target: 'https://api.example.com', // 后端真实域名 changeOrigin: true, // 开启后,请求头的origin会变成target的域名 pathRewrite: { '^/api': '' } // 把请求路径里的“/api”替换成空字符串 } } } }
举个请求的例子:前端用 axios 发请求 axios.get('/api/user')
,经过代理后,实际发给后端的请求是 https://api.example.com/user
(因为 pathRewrite
把 /api
去掉了)。
多代理场景咋配?
如果项目要同时代理多个后端域名(比如用户接口和管理接口),可以这样写:
devServer: { proxy: { '/user-api': { // 用户模块接口 target: 'https://user.example.com', changeOrigin: true, pathRewrite: { '^/user-api': '' } }, '/admin-api': { // 管理模块接口 target: 'https://admin.example.com', changeOrigin: true, pathRewrite: { '^/admin-api': '' } } } }
前端请求 /user-api/login
会代理到 https://user.example.com/login
,请求 /admin-api/list
会代理到 https://admin.example.com/list
,灵活区分不同模块的接口~
proxy实际开发咋用?
配置好 proxy 后,前端发请求时要注意和代理规则匹配,还要分清开发环境和生产环境的区别。
结合axios发请求
很多项目用 axios 发请求,可以在 main.js
里配置基础路径,让所有请求自动带上代理前缀:
import axios from 'axios' axios.defaults.baseURL = '/api' // 和proxy的key“/api”对应 // 登录请求示例 axios.post('/login', { username: 'xxx', password: 'xxx' }) .then(res => { console.log(res.data) })
这样,请求会先发到本地 devServer(http://localhost:8080/api/login
),再由 devServer 转发到后端域名。
开发vs生产环境的区别
proxy 只在开发环境生效(执行 npm run serve
时)!因为生产环境没有 webpack-dev-server
,部署项目时要靠后端配置 CORS 或者用 nginx 反向代理,所以开发时用 proxy 绕开跨域,生产时换其他方案,这点一定要注意~
验证代理是否生效
可以打开浏览器的「Network」面板,看请求的 URL:如果请求地址是 http://localhost:8080/api/login
,但响应数据来自后端域名,说明代理成功,如果请求地址直接是后端域名,说明代理没生效,得回去检查配置~
proxy和其他跨域方案有啥不同?
前面提了 CORS、JSONP,再加上生产环境用的 nginx,和 proxy 对比看看各自的优劣:
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
proxy | 开发阶段前端自主解决 | 不依赖后端,支持所有请求方法,配置简单 | 仅开发环境可用 |
CORS | 生产+开发环境 | 生产环境通用,一劳永逸 | 开发阶段需后端配合配置 |
JSONP | 老旧项目兼容 | 无需额外服务,利用script标签 | 仅支持GET,需后端配合格式 |
nginx | 生产环境部署 | 性能好,适合线上反向代理 | 开发阶段用不上,配置复杂 |
能看出来,proxy 是开发阶段前端最友好的方案:不用等后端,自己配几行代码就能解决跨域,还支持 POST、PUT 等请求方法,日常开发首选~
proxy配置常见问题咋解决?
配了 proxy 却不生效?接口返回 404?跨域问题还在?别慌,这些坑大多有规律,逐一排查:
代理配置不生效
- 检查配置文件:确认
vue.config.js
存在,且devServer.proxy
配置正确,改了配置后要重启devServer(重新执行npm run serve
)。 - 路径匹配问题:proxy 的 key 是
/api
,但请求路径是/Api
(大小写敏感),或者请求路径是/api2
(没匹配到/api
),都会导致代理失效。 - changeOrigin没开:如果后端验证
origin
,没设changeOrigin: true
会被后端拦截,记得打开。
代理后接口404
- target地址错误:检查后端域名是否写对(比如少了
https://
,或者域名拼写错了),还要确认后端服务是否正常启动。 - pathRewrite错误:比如前端请求是
/api/v1/login
,但pathRewrite: { '^/api': '' }
会把路径变成/v1/login
,如果后端接口是/api/v1/login
,就会404,这时候要确认后端接口的真实路径,调整pathRewrite
(比如改成'^/api': '/api'
,或者后端接口确实没有/api
前缀)。
跨域问题仍存在
- 请求没走代理:看浏览器 Network 里的请求 URL,如果是后端域名直接请求,说明代理没匹配到(比如请求路径是
/abc
,但 proxy 配的是/api
)。 - 多个代理规则冲突:webpack-dev-server 的 proxy 是按顺序匹配的,把更具体的规则放前面(
/api/v1
要比/api
先配),避免优先级问题。
Vue2 里的 proxy 是开发阶段解决跨域的“神器”:通过 webpack-dev-server 做中间代理,让前端请求绕开浏览器同源策略,配置时要注意 target
、changeOrigin
、pathRewrite
这几个关键项,结合 axios 发请求时要匹配代理前缀,还要分清开发和生产环境的区别,碰到问题时,从配置文件、路径匹配、后端服务这几个方向排查,基本能解决90%的坑~
现在再回头看开头的跨域报错,是不是觉得 proxy 没那么神秘了?下次开发时碰到跨域,直接配 proxy 开干就完事儿~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。