【vueconfig-proxy代理解决跨域问题】

代理

前言:在 Vue 项目中,接口请求可以通过 vue.config.js 配置代理,解决跨域问题。
在项目中,嵌入页面中的接口,也是可正常走开发环境代理。

  • 开发环境代理:在 vue.config.js 中的 devServer.proxy 配置只在开发时生效
  • 生产环境:部署后代理配置无效,需要直接请求后端地址,需要其他方案处理跨域。

代理配置的工作原理

vue.config.js 中的代理配置:

javascript 复制代码
// vue.config.js
module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://api.example.com',  // 真实后端地址
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''  // 重写路径,去掉 /api 前缀
        }
      }
    }
  }
}

前端代码中使用:

javascript 复制代码
// 开发环境:请求会被代理到 http://api.example.com
// 生产环境:需要配置正确的 baseURL
methods: {
  async fetchData() {
    // 开发时请求本地 /api/users,会被代理到 http://api.example.com/users
    const response = await axios.get('/api/users');
    
    // 或者直接请求完整路径
   const response2 = await axios.get('http://localhost:8080/api/users');
  }
}

何时会走代理?

开发环境(npm run serve):

  • 请求以 /api 开头的路径
  • 请求的域名与当前开发服务器相同(localhost:8080)
  • 会经过 devServer 的代理配置
javascript 复制代码
// 以下情况会触发代理:
axios.get('/api/users')                    // ✓ 会代理
axios.get('/api/products')                 // ✓ 会代理
axios.get('http://localhost:8080/api/data') // ✓ 会代理

// 以下情况不会走代理:
axios.get('https://api.example.com/data')  // ✗ 直接请求,不走代理
axios.get('/users')                        // ✗ 不以 /api 开头
axios.get('http://other-domain.com/api')  // ✗ 不同域名

生产环境(npm run build):

  • 代理配置不生效
  • 需要直接请求后端真实地址
  • 或者配置生产环境 API 地址

完整的项目配置示例

方案一:环境变量配置

javascript 复制代码
// .env.development
VUE_APP_API_BASE_URL=/api

// .env.production
VUE_APP_API_BASE_URL=https://api.yourdomain.com

// src/utils/request.js
import axios from 'axios';

const request = axios.create({
  baseURL: process.env.VUE_APP_API_BASE_URL,
  timeout: 10000
});

export default request;

// 在组件中使用
import request from '@/utils/request';

methods: {
  async getUsers() {
    // 开发环境:/api/users → 代理到真实后端
    // 生产环境:https://api.yourdomain.com/users
    const response = await request.get('/users');
    return response.data;
  }
}

方案二:动态判断环境

javascript 复制代码
// src/api/index.js
import axios from 'axios';

// 判断当前环境
const isDevelopment = process.env.NODE_ENV === 'development';

const apiClient = axios.create({
  baseURL: isDevelopment ? '/api' : 'https://api.yourdomain.com',
  timeout: 10000
});

// 请求拦截器
apiClient.interceptors.request.use(config => {
  // 可以在这里添加 token 等
  const token = localStorage.getItem('token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

export default apiClient;

实践示例

javascript 复制代码
// 1. 创建统一的请求封装
// src/services/api.js
import axios from 'axios';

class ApiService {
  constructor() {
    this.client = axios.create({
      baseURL: this.getBaseUrl(),
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json'
      }
    });
    
    this.setupInterceptors();
  }
  
  getBaseUrl() {
    if (process.env.NODE_ENV === 'development') {
      return '/api';
    }
    return process.env.VUE_APP_API_URL || 'https://api.production.com';
  }
  
  setupInterceptors() {
    // 请求拦截器
    this.client.interceptors.request.use(config => {
      const token = localStorage.getItem('access_token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
      return config;
    });
    
    // 响应拦截器
    this.client.interceptors.response.use(
      response => response.data,
      error => {
        if (error.response?.status === 401) {
          // token 过期处理
          this.handleUnauthorized();
        }
        return Promise.reject(error);
      }
    );
  }
  
  // 封装常用方法
  get(url, params = {}) {
    return this.client.get(url, { params });
  }
  
  post(url, data = {}) {
    return this.client.post(url, data);
  }
  
  // 更多方法...
}

export default new ApiService();

// 2. 在组件中使用
import api from '@/services/api';

export default {
  methods: {
    async loadData() {
      try {
        const users = await api.get('/users');
        const products = await api.post('/products/search', { category: 'electronics' });
        // 处理数据
      } catch (error) {
        // 统一错误处理
        console.error('请求失败:', error);
      }
    }
  }
};
相关推荐
huohuopro2 小时前
Vue3 Webview 转 Android 虚拟导航栏遮挡问题记录
android·vue
码界筑梦坊1 天前
332-基于XGBoost与SHAP的可穿戴设备亚健康风险识别系统
python·数据分析·flask·vue·毕业设计
上单带刀不带妹1 天前
【Axios 实战】网络图片地址转 File 对象,附跨域解决方案
开发语言·前端·javascript·vue
SuperEugene1 天前
前端模块化与 import/export入门:从「乱成一团」到「清晰可维护」
前端·javascript·面试·vue
~央千澈~2 天前
优雅草正版授权系统 - 优雅草科技开源2月20日正式发布
python·vue·php·授权验证系统
Roc.Chang3 天前
Vite 启动报错:listen EACCES: permission denied 0.0.0.0:80 解决方案
linux·前端·vue·vite
PD我是你的真爱粉3 天前
Vite 项目搭建与Pinia状态管理
前端框架·vue
麦麦大数据3 天前
F071_vue+flask基于YOLOv8的实时目标检测与追踪系统
vue.js·yolo·目标检测·flask·vue·视频检测
lyyl啊辉4 天前
1. Vue3简介
vue.js·vue
lyyl啊辉4 天前
4. Vue-Router机制
vue