PROXY_GUIDE.md 7.4 KB

Vite 代理配置指南

概述

本项目使用 Vite 的代理功能来解决开发环境的跨域问题。

代理配置

配置文件

代理配置在 vite.config.ts 中:

server: {
  proxy: {
    // 代理所有 /api 开头的请求
    "/api": {
      target: "http://localhost:8080",
      changeOrigin: true,
      rewrite: (path) => path.replace(/^\/api/, ""),
    },

    // 代理系统接口
    "/sys": {
      target: "http://localhost:8080",
      changeOrigin: true,
    },

    // 代理 WebSocket
    "/websocket": {
      target: "http://localhost:8080",
      changeOrigin: true,
      ws: true,
    },
  },
}

工作原理

开发环境

在开发环境中(npm run dev):

  1. 前端运行在 http://localhost:3000
  2. 后端运行在 http://localhost:8080
  3. 所有以 /api/sys 开头的请求会被代理到后端

请求流程:

浏览器请求: http://localhost:3000/sys/user/list
    ↓
Vite 代理: http://localhost:8080/sys/user/list
    ↓
后端响应

生产环境

在生产环境中(npm run build):

  1. 前端打包后部署到服务器
  2. 使用完整的 API 地址(从环境变量读取)
  3. 不经过代理,直接请求后端

请求流程:

浏览器请求: https://api.example.com/sys/user/list
    ↓
后端响应

环境变量配置

开发环境 (.env.development)

# 开发环境使用本地后端
VITE_API_BASE_URL=http://localhost:8080

生产环境 (.env.production)

# 生产环境使用实际后端地址
VITE_API_BASE_URL=https://api.example.com

代理规则说明

1. /api 路径代理

"/api": {
  target: "http://localhost:8080",
  changeOrigin: true,
  rewrite: (path) => path.replace(/^\/api/, ""),
}

作用:/api 前缀去掉后转发

示例:

  • 请求:/api/users/list
  • 转发:http://localhost:8080/users/list

2. /sys 路径代理

"/sys": {
  target: "http://localhost:8080",
  changeOrigin: true,
}

作用: 保留 /sys 前缀转发

示例:

  • 请求:/sys/user/list
  • 转发:http://localhost:8080/sys/user/list

3. WebSocket 代理

"/websocket": {
  target: "http://localhost:8080",
  changeOrigin: true,
  ws: true,
}

作用: 代理 WebSocket 连接

常见问题

1. 代理不生效

原因: 请求路径不匹配代理规则

解决: 确保请求路径以配置的前缀开头(如 /api/sys

// ✅ 正确 - 会被代理
http.get("/sys/user/list");

// ❌ 错误 - 不会被代理
http.get("http://localhost:8080/sys/user/list");

2. 跨域问题

原因: changeOrigin 未设置为 true

解决: 确保代理配置中有 changeOrigin: true

"/api": {
  target: "http://localhost:8080",
  changeOrigin: true, // 必须设置
}

3. Cookie 无法携带

原因: 跨域请求默认不携带 Cookie

解决: 在代理配置中添加 Cookie 相关配置

"/api": {
  target: "http://localhost:8080",
  changeOrigin: true,
  cookieDomainRewrite: "localhost",
}

4. HTTPS 证书问题

原因: 后端使用自签名证书

解决: 添加 secure: false

"/api": {
  target: "https://localhost:8443",
  changeOrigin: true,
  secure: false, // 忽略证书验证
}

高级配置

1. 多个后端服务代理

server: {
  proxy: {
    // 用户服务
    "/api/user": {
      target: "http://localhost:8081",
      changeOrigin: true,
    },
    // 订单服务
    "/api/order": {
      target: "http://localhost:8082",
      changeOrigin: true,
    },
  },
}

2. 根据环境变量动态配置

import { loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");

  return {
    server: {
      proxy: {
        "/api": {
          target: env.VITE_API_BASE_URL,
          changeOrigin: true,
        },
      },
    },
  };
});

3. 请求日志

"/api": {
  target: "http://localhost:8080",
  changeOrigin: true,
  configure: (proxy, options) => {
    proxy.on("proxyReq", (proxyReq, req, res) => {
      console.log("代理请求:", req.method, req.url);
    });
    proxy.on("proxyRes", (proxyRes, req, res) => {
      console.log("代理响应:", proxyRes.statusCode, req.url);
    });
  },
}

4. 请求重写

"/api": {
  target: "http://localhost:8080",
  changeOrigin: true,
  rewrite: (path) => {
    // 移除 /api 前缀
    const newPath = path.replace(/^\/api/, "");
    console.log(`重写路径: ${path} -> ${newPath}`);
    return newPath;
  },
}

部署注意事项

1. Nginx 反向代理

生产环境通常使用 Nginx 做反向代理:

server {
    listen 80;
    server_name example.com;

    # 前端静态资源
    location / {
        root /var/www/html;
        try_files $uri $uri/ /index.html;
    }

    # 后端 API 代理
    location /api {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /sys {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

2. 前后端分离部署

如果前后端部署在不同域名:

前端: https://www.example.com
后端: https://api.example.com

需要在 .env.production 中配置完整的后端地址:

VITE_API_BASE_URL=https://api.example.com

同时后端需要配置 CORS:

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("https://www.example.com");
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        config.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

调试技巧

1. 查看代理日志

vite.config.ts 中添加日志:

server: {
  proxy: {
    "/api": {
      target: "http://localhost:8080",
      changeOrigin: true,
      configure: (proxy) => {
        proxy.on("error", (err) => {
          console.log("代理错误:", err);
        });
        proxy.on("proxyReq", (proxyReq, req) => {
          console.log("发送请求:", req.method, req.url);
        });
        proxy.on("proxyRes", (proxyRes, req) => {
          console.log("收到响应:", proxyRes.statusCode, req.url);
        });
      },
    },
  },
}

2. 使用浏览器开发者工具

  1. 打开 Network 面板
  2. 查看请求的 URL
  3. 检查请求头和响应头
  4. 确认是否被代理

3. 测试代理配置

# 启动开发服务器
pnpm dev

# 在浏览器中访问
http://localhost:3000

# 在控制台测试请求
fetch('/sys/user/list').then(r => r.json()).then(console.log)

参考资料