【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);
      }
    }
  }
};
相关推荐
天下无贼!1 天前
【功能实现】基于Vue3+TS实现大文件分片上传
开发语言·javascript·node.js·vue·html5
曲幽1 天前
FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南”
python·vue·fastapi·web·vite·proxy·cors·env
落魄江湖行1 天前
入门篇四:Nuxt4布局系统:让页面框架复用变得简单
前端·vue·nuxt4
色空大师1 天前
网站搭建实操(十)前端搭建
前端·webpack·vue·网站·论坛
.生产的驴3 天前
Vue3 超大字体font-slice按需分片加载,极速提升首屏速度, 中文分片加载方案,性能优化
前端·vue.js·windows·青少年编程·性能优化·vue·rescript
宁波阿成4 天前
族谱管理系统架构分析与亮点总结
java·系统架构·vue·ruoyi-vue·族谱
不想上班只想要钱4 天前
模板里 item.xxx 报错 ,报 item的类型为未知
前端·vue
一只小阿乐4 天前
js流式模式输出 函数模式使用
开发语言·javascript·ai·vue·agent·流式数据·node 服务
淡忘_cx4 天前
解决 Vite EACCES 权限错误:从报错到修复的完整指南
前端·vue