Vue 项目之 Webpack 中 devServer 的 proxy 配置(2)
1. 配置 devServer.proxy
下面来配置代理,我们通常会这样做:
...
module.exports = {
...
devServer: {
...
proxy: {
'/api': 'http://localhost:8000'
}
},
...
}
'/api': 'http://localhost:8000'
这行代码相当于是一个映射关系,意思是如果对 /api
进行请求,到时候会将其代理到 http://localhost:8000
(准确来说其实是被代理去请求 http://localhost:8000/api
这个地址)。那就意味着我们在发送网络请求时需要这样来写:
axios.get('/api/moment?offset=0&size=10').then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
我们用 /api
替换掉了之前的 http://localhost:8000
,就是说我们在源代码中使用的是 /api
(到时候它会被映射到 http://localhost:8000
中去),让它作为代理帮我们去请求 http://localhost:8000
中的数据,请求到数据后再返回到我们的 response
(即上面代码中的 res
)里面,我们就能拿到对应的数据了。
但是,目前这样配置还会有一些问题。我们 npm run serve
重新运行代码看下效果:
可以看到,之前的跨域访问问题已经不见了,但是现在又报了另外一个错误:请求的资源没找到。报错信息显示现在加载的是 http://localhost:8010/api/moment?offset=0&size=10
这个路径的资源,也就是说,我们上面的配置('/api': 'http://localhost:8000'
)本质上会将 /api
映射成 http://localhost:8010/api
,而不是我们希望的 http://localhost:8010
这个映射结果。如果我们希望映射的结果中不带这个 /api
,就需要通过 pathRewrite
属性重写路径,因此,'/api'
后面跟得一般不是字符串,而是一个对象:
...
module.exports = {
...
devServer: {
...
proxy: {
'/api': {
target: 'http://localhost:8000',
pathRewrite: {
'^/api': '' // 将开头的 '/api' 替换成空字符串(^ 是开头的意思,'^/api' 表示以 /api 开头)
}
}
}
},
...
}
因为我们现在发送的网络请求已经改成了 /api
开头的格式,所以就会匹配上 pathRewrite
的规则,那么最终映射的结果中就不会有 /api
了,因此就能请求到我们想要的路径了。我们重新运行 npm run serve
命令看下效果:
可以看到,这次我们就能成功请求到本地服务器中的数据了。
以上,就是开发阶段在本地解决浏览器跨域问题的方法,即通过配置 devServer.proxy
来解决,当然,这只是关于 proxy
最基本的配置,下面我们再来讲两个 proxy
的配置项:secure
和 changeOrigin
。
secure
默认情况下,devServer.proxy
不会接受运行在 HTTPS
协议上且证书无效的后端服务器,意思是假如我们代理到的目标地址是 https://localhost:8000
,即目标是 HTTPS
协议的服务器,而 HTTPS
协议的服务器是必须要携带对应的安全证书的,但如果没有配置对应的证书,这里就不会代理成功。要想在没有证书的情况下,依然能成功代理到目标是 HTTPS
协议的服务器上,我们就需要设置 secure: false
(默认情况下,secure
为 true
):
...
module.exports = {
...
devServer: {
...
proxy: {
'/api': {
target: 'https://localhost:8000',
pathRewrite: {
'^/api': '' // 将开头的 '/api' 替换成空字符串(^ 是开头的意思,'^/api' 表示以 /api 开头)
},
secure: false // 如果目标是 http 协议的地址,则可以不配置 secure
}
}
},
...
}
changeOrigin
changeOrigin
表示是否修改源。当前(配置了 devServer.proxy
后),我们在源代码中发送网络请求时是经过了一层代理的(因为直接发送网络请求在浏览器中会出现跨域问题),让代理去帮我们发送网络请求,代理请求到数据后再将数据返回给我们。在这一过程中,我们源代码中是通过 /api
开头的路径去发送请求的,前面说过,默认情况下它其实会加上当前的源(比如 http://localhost:8010
),即实际请求的路径是以 http://localhost:8010/api
开头的。虽然这个源(http://localhost:8010
)后面经过代理变成了 http://localhost:8000
,但请求的目标服务器(服务器会解析请求的 header
,有些服务器可能会对 header
进行验证,看下 header
里面的内容对不对,如果不对的话服务器是不会随便返回对应的数据的,因为服务器可能担心请求来自爬虫软件,因为有些爬虫软件会通过代理服务器爬取我们的数据,所以目标服务器可能会对源进行校验)接收到的源其实还是 http://localhost:8010
,如果该服务器有对源做校验,可能就不会给我们返回数据了。这时,我们就可以将 changeOrigin
属性设置为 true
,让 devServer
服务器内部帮我们将发送网络请求时的源修改掉,改成代理的目标地址对应的源。这样一来,不管目标服务器上有没有对源做校验,就都没有问题了。
我们通过查看源码可以看到 changeOrigin
设置为 true
时,修改的其实是代理请求中的 headers
中的 host
属性的值:
更多关于 devServer.proxy
的信息可以查阅官方文档:webpack.js.org/configurati…
2. historyApiFallback
historyApiFallback
是开发中非常常见的属性,它主要的作用是解决SPA
页面在路由跳转之后,进行页面刷新时,返回404
错误的问题。boolean
值:默认是false
- 如果设置为
true
,那么在刷新时,返回404
错误时,会自动返回index.html
的内容;
- 如果设置为
object
类型的值,可以配置rewrites
属性(了解):- 可以配置
from
来匹配路径,决定要跳转到哪一个页面;
- 可以配置
- 事实上
devServer
中的historyApiFallback
功能是通过connect-history-api-fallback
库来实现的:- 详情可以查看 connect-history-api-fallback 文档
关于 historyApiFallback
的具体配置我们后面再来讲。
转载自:https://juejin.cn/post/7056007292059123749