chaihongjun.me

Vite本地开发测试解决跨域CORS问题

Vite本地开发测试中遇到跨域问题,主要是由于浏览器的同源策略(Same-Origin Policy)限制所导致的。同源策略是浏览器的一种安全机制,它规定了浏览器如何限制一个源(包括协议、域名和端口)的文档或脚本与来自另一个源的资源进行交互。这种限制的目的是防止恶意网站通过跨域请求来窃取用户的敏感信息或执行潜在的安全漏洞。

在Vite本地开发环境中,前端应用通常运行在一个源(例如localhost:5173),而后端API可能运行在不同的源(例如localhost:8080)。当前端应用尝试向后端API发送请求时,由于两个源不同,浏览器的同源策略会阻止这种跨域请求,从而导致跨域问题。

为了解决这个问题,Vite提供了内置的HTTP代理服务器功能。通过在Vite的配置文件(如vite.config.js或vite.config.ts)中配置代理规则,开发者可以将前端应用发出的请求转发到实际的后端服务上,从而绕过浏览器的同源策略限制。具体来说,配置代理服务器需要定义一系列的代理规则,每个代理规则包含一个或多个前缀路径,以及目标服务器的URL。当前端应用在开发环境下运行时,Vite服务器会监听所有请求。如果请求的URL匹配任何代理规则的前缀,Vite服务器会拦截这个请求,并将其转发到代理规则中定义的目标服务器。这个过程对前端应用是透明的,即前端应用无需关心请求是如何被转发的,只需要按照正常的请求方式发出请求即可。

需要注意的是,这种代理机制仅在开发环境中有效。在生产环境中,通常需要后端服务正确配置CORS(Cross-Origin Resource Sharing)策略或其他跨域支持,以确保前端应用能够顺利地与后端服务进行交互。因此,在将应用部署到生产环境之前,开发者需要确保后端服务已经配置了适当的跨域支持策略。

一个例子来说明,假设API接口地址类似如下:

https://chaihongjun.me/data/api/getPosts

https://chaihongjun.me/data/api/getUsers

我们设置axios封装之后的baseURL是 "/":

// 创建 axios 实例
const service = axios.create({
  baseURL: '/',
  timeout: 3000, // 请求超时时间
})

然后请求封装(必须包含/api):

export function getPosts() {
  return service({
    url: `/api/getPosts`,
    method: 'get'
  });
}

export function getUsers() {
  return service({
    url: `/api/getUsers`,
    method: 'post'
  });
}

那么Vite.config.js的代理配置如下:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'


// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(),
  ],
  resolve: {
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    alias: {
      '@': '/src',
    },
  },
  // 这里是代理部分
   server: {
    proxy: {
      '/api': {
        target: 'https://chaihongjun.me/data/api',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '') // 去掉 /api 前缀
      }
    }
  }
})

特别注意target项的值,它的值是全部API接口的统一部分。

vite开发服务器的代理功能,把所有/api开头的请求都转发到target指向的地址

https://chaihongjun.me/data/api

所以当请求是/api/getPosts的时候,相当于访问:

https://chaihongjun.me/data/api+/api/getPosts

这与实际的接口地址不符合,但是配置里有一项配置:

rewrite: (path) => path.replace(/^\/api/, '') // 去掉请求url  /api 前缀

把/api/getPosts请求改写成/getPosts

所以最后相当于:

https://chaihongjun.me/data/api+/getPosts

与实际API一模一样

知识共享许可协议本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。作者:柴宏俊»