如上问题描述,
Vue设置baseURL后即使设置了devServer也不能实现代理,baseURL为空就行,这是为什么?
如果baseURL设置则接口调用失败,实际接口没有替换
但是如果设置baseURL为空,则可以代理
这就很奇怪,理论上在开发环境中,devServer.proxy 应该能够正确地将请求代理到指定的后端服务器地址。也就是不管你设置了baseURL还是没有设置都可以,但实际是如果设置baseURL就不会发生代理。
这是为什么?有没有大佬能指导一下呢?
如上问题描述,
Vue设置baseURL后即使设置了devServer也不能实现代理,baseURL为空就行,这是为什么?
如果baseURL设置则接口调用失败,实际接口没有替换
但是如果设置baseURL为空,则可以代理
这就很奇怪,理论上在开发环境中,devServer.proxy 应该能够正确地将请求代理到指定的后端服务器地址。也就是不管你设置了baseURL还是没有设置都可以,但实际是如果设置baseURL就不会发生代理。
这是为什么?有没有大佬能指导一下呢?
Vue设置baseURL后即使设置了devServer也不能实现代理,baseURL为空就行,这是为什么?
因为 Axios 设置了 baseURL
之后,会请求到设置的 baseURL
目标上。没有设置 baseURL
则浏览器会自动拼接当前 host
信息到请求的目标URL上。
所以设置了 baseURL
之后,可能会不走 VueCLI
或者 Vite
的 devServer
实现代理。而不设置 baseURL
默认情况下则一定会通过本地的 devServer
。
理论上在开发环境中,devServer.proxy 应该能够正确地将请求代理到指定的后端服务器地址。也就是不管你设置了baseURL还是没有设置都可以,但实际是如果设置baseURL就不会发生代理。
你的理解是错的。实际情况是本地开发时,VueCLI
或者 Vite
会启动一个本地的HTTP服务,也就是你理解中的 devServer
,如果想要将请求代理到在 devServer
中配置的目标地址(后端接口地址)。
那么需要你把请求发送到本地启动的这个 devServer
,通过这个本地代理转发到目标服务器上。
本质是通过本地的 devServer
中转了一下,把请求的目标服务器和发起请求的host信息变成一致的,这样浏览器就不会认为是同源的,从而避免出现跨域限制。
以下是一下图例方便你理解:
正常情况下,客户端直接请求服务器,服务器返回响应内容给客户端。这个时候如果客户端和服务器是非同源的,那么浏览器会进行跨域拦截。
所以我们在本地开发时经常会借助本地启动的代理服务去转发,使得客户端和本地的代理服务出于同源环境下。跨域限制只会出现在浏览器端,服务端是不会有跨域情况的
按照当前你的实际情况,是给Axios配置了 baseURL
直接向目标服务器发起了请求,而不是通过代理服务器转发到目标服务器,自然会出现跨域的问题。
所以我们在配置 baseURL
的时候,经常会借助环境变量来实现启动不同的服务,配置不同的 baseURL
信息,保证请求是同源的。
那么一般我们会这样配置 Axios
:
const service: AxiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_PATH, // API服务器地址
timeout: 50000, // 全局超时时间
});
本地的 Vite
或者 VueCLI
代理配置中使用环境变量指定目标服务器地址:
const viteConfig = defineConfig((mode: ConfigEnv) => {
...
server: {
host: '0.0.0.0', // 指定开发服务监听的IP地址,设置为 0.0.0.0 或者 true 将监听所有地址
port: env.VITE_PORT as unknown as number, // 指定开发服务端口号
open: env.VITE_OPEN === 'true', // 是否自动打开浏览器
hmr: true, // 启用热更新
proxy: {
'/api': {
target: env.VITE_PROXY_TARGET, // 目标服务器地址
ws: true,
changeOrigin: true, // 是否修改请求头中的 Origin 字段
rewrite: (path) => path.replace(/^\/api/, ''),
},
'^/ws/info/.*': {
target: env.VITE_PROXY_TARGET, // 目标服务器地址
ws: true,
changeOrigin: true,
},
},
},
}
以及在环境变量中声明对应的地址:
# 环境名称
VITE_ENV_TITLE = '开发环境'
# port 端口号
VITE_PORT = 8888
# 浏览器自动打开
VITE_OPEN = true
# 编译模式
ENV = 'development'
# 前端根目录地址
VITE_PUBLIC_PATH = /
# API地址
VITE_API_PATH = /api
# 目标服务地址
VITE_PROXY_TARGET = http://10.xxx.xxx.xxx:9999
# 环境名称
VITE_ENV_TITLE = '生产环境'
# port 端口号
VITE_PORT = 8888
#浏览器自动打开
VITE_OPEN = true
# 编译模式
ENV = 'production'
# 前端根目录地址
VITE_PUBLIC_PATH = /
# API地址
VITE_API_PATH = https://www.domian.com/api
# 目标服务地址
VITE_PROXY_TARGET = http://10.xxx.xxx.xxx:9999
后者才是符合预期的。
proxy 的原理是将请求到 proxy 的请求转发到你设置的地址。如果你的 axios 配置了地址,那么前端就无法请求到 proxy 服务上,自动就无法转发了。当你 axios 的 base 留空时,默认时候页面的 base 地址,也就能正常请求到 proxy 服务实现请求转发了。