【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);
      }
    }
  }
};
相关推荐
东东5165 小时前
基于Web的智慧城市实验室系统设计与实现vue + ssm
java·前端·人工智能·后端·vue·毕业设计·智慧城市
不甘平凡的小鸟7 小时前
vue3与cef3交互
前端·vue·cef3
武哥聊编程8 小时前
【原创精品】基于Springboot3+Vue3的服装租赁平台
spring boot·mysql·vue·课程设计
weixin_439937761 天前
tortoiseGit 使用
java·前端·git·vue
任小栗1 天前
uniappx实现app壳子,可直接拿来用
vue·uniapp
奔跑的web.1 天前
前端使用7种设计模式的核心原则
前端·javascript·设计模式·typescript·vue
千寻技术帮1 天前
10410_基于Springboot的文化旅游宣传网站
spring boot·后端·vue·源码·旅游·安装·在线旅游
iRuriCatt2 天前
智慧景区管理系统 | 计算机毕设项目
java·前端·spring boot·vue·毕设
吹牛不交税2 天前
admin.net框架使用记录
vue·.netcore