vue跨域请求接口代理方式 - 完整解决方案与实战教程

在前后端分离的开发模式下,Vue 项目通常运行在本地开发服务器(如 http://localhost:8080),而后端 API 却部署在另一台服务器或另一个端口上(如 http://api.example.comhttp://localhost:3000)。此时浏览器会因为同源策略而拦截请求,控制台报出 “Access to XMLHttpRequest at 'xxx' from origin 'xxx' has been blocked by CORS policy” 的错误。更让人头疼的是,很多开发者明明在本地配置了代理,打包上线后却依然 404 或跨域,核心痛点在于混淆了“开发环境代理”与“生产环境代理”的边界,以及没有理解 Vue CLI / Vite 代理配置中 rewrite 与 pathRewrite 的差异。本文将从实际排坑角度出发,带你彻底搞懂 Vue 跨域请求接口代理的几种方式。

问题现象

典型报错信息如下,通常出现在浏览器控制台 Network 面板中:

原因分析

浏览器同源策略要求协议、域名、端口三者完全一致。Vue 开发服务器默认启动在 localhost:8080,而后端接口若在 localhost:3000,端口不同即构成跨域。解决方式有两种:后端开启 CORS,或前端使用代理服务器转发请求。代理的本质是让浏览器请求同源的开发服务器,再由开发服务器(Node.js 层)转发到真实后端,从而绕过浏览器限制。但很多开发者误以为代理配置能带到生产环境,实际上 Vue CLI 和 Vite 的 devServer.proxy 只在开发阶段生效,生产环境必须依赖 Nginx 或后端 CORS。

解决方案(附完整代码)

下面分别给出 Vue CLI(webpack)和 Vite 两种主流脚手架的代理配置方式,并附带完整注释。

方案一:Vue CLI 项目(vue.config.js)

在项目根目录创建或修改 vue.config.js

// vue.config.js
module.exports = {
  devServer: {
    // 开发服务器端口,默认 8080
    port: 8080,
    proxy: {
      // 匹配所有以 /api 开头的请求路径
      '/api': {
        // 目标后端地址,注意不要加 /api 后缀
        target: 'http://localhost:3000',
        // 允许跨域,本质是修改请求头中的 Origin
        changeOrigin: true,
        // 是否启用 websocket 代理,一般 false
        ws: false,
        // 路径重写:把 /api 前缀去掉再转发给后端
        // 例如 /api/user -> http://localhost:3000/user
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  }
}

前端请求时统一使用相对路径:

// axios 实例配置
import axios from 'axios'

const request = axios.create({
  // 这里写 /api,开发环境会被代理拦截并转发
  baseURL: '/api',
  timeout: 5000
})

export default request

方案二:Vite 项目(vite.config.js)

Vite 的代理配置位于 server.proxy,语法与 http-proxy 一致,但注意 Vite 没有 pathRewrite,而是使用 rewrite

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

export default defineConfig({
  plugins: [vue()],
  server: {
    port: 5173,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        // Vite 中使用 rewrite 而不是 pathRewrite
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

方案三:生产环境 Nginx 反向代理(必备)

开发代理不能用于生产,打包后需要 Nginx 转发:

# nginx.conf 片段
server {
  listen 80;
  server_name your-domain.com;

  # 前端静态资源
  location / {
    root /usr/share/nginx/html;
    index index.html;
    try_files $uri $uri/ /index.html;
  }

  # 接口代理
  location /api/ {
    # 后端真实地址,注意末尾斜杠
    proxy_pass http://backend-server:3000/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

排查步骤与避坑清单

  1. 确认代理是否生效:修改配置后必须重启开发服务器,热更新不会重新加载 proxy 配置。
  2. 检查 baseURL 与代理前缀是否一致:如果 axios 的 baseURL 是 /api,则 proxy 的 key 也必须是 /api,否则无法匹配。
  3. 区分 pathRewrite 与 rewrite:Vue CLI 用 pathRewrite,Vite 用 rewrite,写错不会报错但代理不生效。
  4. target 末尾不要带斜杠:写成 http://localhost:3000/ 可能导致路径拼接异常,推荐不带斜杠。
  5. 生产环境不要依赖 devServer:打包后 vue.config.js 中的 proxy 完全失效,必须配置 Nginx 或让后端开启 CORS。
  6. 检查后端是否监听 0.0.0.0:如果后端只监听 127.0.0.1,代理转发可能被拒绝。
  7. 使用 curl 验证:在终端执行 curl http://localhost:8080/api/user,若返回后端数据则代理成功。

掌握以上三种方式,你就能在开发阶段用代理优雅解决跨域,在生产环境用 Nginx 稳定转发,彻底告别 CORS 报错。