Vue如何处理浏览器跨域问题

1. 什么是跨域

跨域问题是由于浏览器同源策略(Same-Origin Policy)所导致的,
同源策略是浏览器的一种安全机制,
限制一个域的网页与另一个域的资源进行交互,
即限制了一个源(协议、域名、端口)下的文档或脚本与另一个源的资源进行交互,
也就是浏览器向不同源(不用协议、不用域名、不同端口)发送ajax请求会失败。

2. 跨域的例子

比如,我们启动的项目,启动了两个服务:

  • 前端端口是5173
  • 后端端口是8080

当浏览器启动后,会先发送请求,到前端服务,比如得到一个登录页面
这个登录页面所在的源,就是http://localhost:5173
在登录页面里,嵌套了一段js代码,里面有一个登录按钮,
当用户点击登录按钮时,会发送请求到后端服务http://localhost:8080
此时ajax请求所在的源是5173,但它请求的目标是8080
这个时候,属于不同的源,
由于浏览器的同源策略限制,该请求会发送失败,这种就是跨域问题。

3. 配置代理 解决跨域问题

配置代理后,请求就不会从5173直接发向8080,
当点击登录按钮,发送异步请求时,会先把请求发向前端服务5173,
此时异步请求所在的源就是5173,所以就不会出现跨域问题,
再由前端服务5173,转发到后端服务8080,
也就是说,该请求是由服务端发起的,就没有跨域问题了。

4. 如何配置代理

4.1 首先在utils中的请求工具request.js里,把写固定的路径修改一下。

在这里插入图片描述
示例代码如下:

//这里边相当于请求的工具,用来定制请求的实例

//导入axios npm install axios
import axios from 'axios';

//导入Message消息提示
import { ElMessage } from 'element-plus';

//定义一个变量,记录公共的前缀,baseURL
// const baseURL = 'http://localhost:8080';
// 这里的'/api'只是给后台访问的请求路径添加一个标识
const baseURL = '/api';
/*  axios.create()方法,把baseURL作为参数传入,
    该方法返回一个请求的实例instance,
    以后发送请求时,就不用axios.get了,
    直接用instance.get就可以 */
const instance = axios.create({baseURL})

/* axios提供的拦截器,
    在请求或响应,被then或catch处理前拦截
    也就是在请求发出之前,有一个请求拦截器
    或在响应到达之前,有一个响应拦截器 */

//添加响应拦截器(这个拦截器本身就是异步的)
instance.interceptors.response.use(
    //成功的回调
    result=>{
        //判断业务状态码
        if(result.data.code === 0){
            return result.data;
        }
        
        //操作失败
        ElMessage.error(result.data.msg?result.data.msg:'服务异常');
        
        //异步操作的状态转换为失败
        return Promise.reject(result.data);
    },
    //失败的回调
    err=>{
        alert('服务异常');
        
        //异步的状态转化成失败的状态
        return Promise.reject(err);
    }
)

//把请求的实例instance导出,供其他地方调用
export default instance;

上述代码中,只是把const baseURL = ‘http://localhost:8080’;
改成了const baseURL = ‘/api’;
意思就是,比如以前写的 const baseURL = ‘http://localhost:8080’;
现在改成 const baseURL = ‘/api’;
这里的 ‘/api’ 其实就是是给后台访问的请求路径添加一个标识,
然后在配置代理里,会把这个 ‘/api’ 替换为我们想要的路径,
api前边并没有写端口号,就会把当前ajax请求所在的源自动拼进去,
就相当于写的http://localhost:5173/api
因为当前ajax代码所处的源,就是刚才页面所处的源http://localhost:5173,
所以当用户点击登录按钮时,请求就发送给5173的这个前端服务,
两个源都是5173,所以不会出现跨域

4.2 在 vite.config.js 配置信息里边,添加 ‘/api’ 的对应配置

在这里插入图片描述
这里的配置,才是真正配置代理的,
这里才是配置请求路径和端口号的地方。

示例代码:

//这里边写的是vue项目的配置信息,如端口号等

import { fileURLToPath, URL } from 'node:url'

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

// https://vite.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    vueDevTools(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
  },

  //server:代表是要做服务相关的配置
  server: {
    //proxy: 指的是要配置一些代理
    proxy: {
      //获取路径中包含了/api的请求,这里的'/api'是指:请求路径中,是否有带/api这部分的路径,如果有/api,就对其进行处理
      '/api': {
        
        target: 'http://localhost:8081', //target:指的是,如果要更换源,要更换成谁,就写谁,这里写的是后台服务所在的源

        changeOrigin: true, //changeOrigin:指的是,是否要更换换源

        secure: false, // 如果目标服务器无 HTTPS,需关闭安全验证

        rewrite: (path) => path.replace(/^\/api/, ''), // rewrite:是路径的重写,这里把/api替换为''
      }
    }
  }
})

为了更好的理解上边的配置,举个例子:
比如发送异步请求,路径是http://localhost:5173/api/user/register,
这个路径中,有 /api,配置信息里的 changeOrigin: true,就会更改源,
把源改为target‘http://localhost:8080’
改完后就变成了http://localhost:8080/api/user/register,
就是把 /api 前边的路径给换了,
同时,rewrite重写路径,把 /api重写成空字符串
最后,路径就是这样的http://localhost:8080/user/register

4.3 Vite 配置代理路径问题

4.3.1 在 Vite 中配置代理时,路径未生效,可能是 版本兼容性导致的。
  • 如果是 Vite 2.x 版本,就用上边示例的配置格式,直接使用 rewrite 配置即可。
  • 如果是 Vite 3.x+ 版本,需要用 configure 包裹代理配置:
  • 检查 Vite 版本的命令
    • 在项目根目录下运行:

      npx vite --version
      

      ./node_modules/.bin/vite --version
      
    • 如果已全局安装 Vite:

      vite --version
      
    • 通过 npm list (这个速度稍慢)

      npm list vite
      
4.3.2 Vite 高版本 配置代理

我当时使用的 Vite 版本 v6.2.4,rewrite 函数的触发条件和路径处理方式,需要显式指定 configure 选项来修改代理行为:

  • 使用 configure 选项​
    Vite 6.x 需要通过 configure 直接操作底层的 http-proxy 实例,才能确保路径重写生效。
  • 显式修改 proxyReq.path
    直接操作代理请求对象的 path 属性
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue(),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    },
  },

  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8081', 
        changeOrigin: true, 
        secure: false, // 如果目标服务器无 HTTPS,需关闭安全验证
        /**
         * Vite 6.x 对代理配置的底层实现进行了优化,
         * rewrite 函数的触发条件 和 路径处理方式 有所变化。
         * 需要显式指定 configure 选项来修改代理行为。
         */
        configure: (proxy) => {
          proxy.on('proxyReq', (proxyReq, req) => {
            //console.log('🚀 http://localhost:8081 代理请求被触发');
            proxyReq.path = req.url.replace(/^\/api/, '')
          })
        }
      }
    }
  }
})

以上就是Vue通过配置代理来解决跨域问题。

  • 这是完整代码
    前端 easy-vue3 持续更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值