如何通过Vite代理配置,实现前端跨域访问?

997 阅读4分钟

跨域问题的产生

“跨域” 其实是和 “同源” 概念是相对的。什么是同源?即当前浏览器页面的URL,和目标请求服务器的URL的协议(HTTP/HTTPS)域名端口完全相同的。

什么是 跨域 ?即协议、域名或端口的任意不同。当然,这里是指当前页面的源(即执行脚本的页面的URL)和请求的目标资源的源(比如API的URL)之间的比较。

举个例子,如果用户正在访问的页面是 example.com:3000/page.html ,而页面中的JavaScript尝试请求api.example.com:8080/data.json, 那么浏览器会比较这两个URL的协议(https/http)、域名(example.com / api.example.com) 和端口(3000 / 8080)。如果这三个中有任何一个不同,就会触发同源策略的限制,导致跨域问题。

Vite 跨域代理设置

浏览器的同源策略对于数据和信息的安全保护非常有效,但是在实际开发过程中会带来很多不便,比如前端和后端各自使用的域名和端口不一致。在开发环境中,可以通过Vite前端设置跨域代理的方式解决跨域问题。

具体来说,就是修改vite.config.js 的配置文件:

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://your-backend-domain.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
        // 其他可选配置
        secure: false, // 禁用 SSL验证(测试环境使用)
        ws: true // 代理 WebSocket
      }
    }
  }
})

在上面的代码配置中,target 是后端服务器的目标地址,changeOrigin: true 代表允许跨域,rewrite的意思是,如果在这个URL请求路径上遇到/api的,那么就会把此请求路径上的/api替换为空字符串。

Vite 配置代理为什么能够解决跨域问题 ?

同源策略是浏览器的同源策略,跨域问题的产生是因为浏览器的同源策略。

事实上,在跨域的情况下,当前端页面的 JS 脚本向后端服务器发送请求后,服务器依旧会产生响应,但是由于同源策略,浏览器会对不符合同源规则的响应进行拦截限制前端脚本对响应内容的访问,因此前端页面的请求会显示无响应或者一些错误信息。

浏览器 会对服务器的响应内容进行同源/跨域检查,但是 服务器 却可以不对服务器的响应内容进行同源/跨域检查。因此,我们可以按照如下的步骤解决跨域问题:

1. 拦截请求

当我们在前端应用中发起以 /api 开头的请求时,Vite 开发服务器会拦截这些请求。因为 Vite 开发服务器运行在与前端应用相同的源上,所以浏览器不会对这些请求进行同源策略的限制

2. 修改请求头(changeOrigin

changeOrigin: true 会修改请求头中的 Origin 字段,使其与目标服务器的域名一致。当请求被转发到后端服务器时,后端服务器会根据 Origin 字段来判断请求的来源。通过将 Origin 字段修改为目标服务器的域名,可以让后端服务器认为请求是从自身发起的,从而绕过部分同源策略的限制。

3. 重写请求路径(rewrite

rewrite 函数用于对请求路径进行重写。在这个例子中,rewrite: (path) => path.replace(/^/api/, '') 会将请求路径中的 /api 替换为空字符串。这样,当请求被转发到后端服务器时,后端服务器接收到的请求路径是符合其接口定义的,而不是包含 /api 前缀的路径。

4. Vite 服务器转发请求

Vite 开发服务器会将拦截并处理后的请求 转发 到 target 所指定的后端服务器地址。由于 Vite 开发服务器与后端服务器之间的请求是 服务器与服务器之间的通信,不受浏览器同源策略的限制,所以可以正常地与后端服务器进行交互。

5. 返回响应

后端服务器接收到请求后,会处理请求并返回响应。Vite 开发服务器会将后端服务器的响应返回给前端应用,从而完成整个请求 - 响应过程。

事实上,如果我们进行了跨域代理的配置,Vite就会自动进行上述的步骤,帮助我们在开发环境中,解决跨域代理问题。

总结

Vite 配置代理是在开发环境中解决跨域问题的一种常见方式。除了代理之外,还有其他一些解决跨域问题的方法,如 Nginx反向代理、CORS(跨域资源共享)等。每种方法都有其优缺点和适用场景,在实际开发和部署中,我们需要根据具体的需求和情况选择合适的解决方法。