前端开发中的跨域问题:Vite 开发环境配置指南
前言
在前端开发过程中,跨域问题是一个经常遇到的挑战。当你的前端应用运行在 http://localhost:5173,而后端 API 运行在 http://2.x.x.x:28xxx 时,浏览器会阻止这种跨域请求。本文将详细介绍如何使用 Vite 的代理功能来解决开发环境中的跨域问题。
什么是跨域?
跨域(Cross-Origin Resource Sharing,CORS)是浏览器的同源策略限制。当以下三个要素中任意一个不同时,就会产生跨域:
- 协议 (Protocol):如
http和https - 域名 (Domain):如
localhost和2.x.x.x - 端口 (Port):如
5173和28xxx
当浏览器检测到跨域请求时,会抛出类似以下的错误:
csharp
Access to XMLHttpRequest at 'http://2.x.x.x:28xxx/login' from origin 'http://localhost:5173'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
解决方案对比
1. 后端配置 CORS(生产环境推荐)
在后端服务器设置响应头,允许指定的源访问:
javascript
// 后端示例(Node.js/Express)
app.use(cors({
origin: 'http://localhost:5173',
credentials: true
}));
优点 :符合生产环境最佳实践
缺点:需要后端配合,开发环境可能无法修改后端
2. 浏览器插件(不推荐)
使用 Chrome 插件禁用 CORS 检查。
优点 :快速
缺点:仅适用于开发,不安全,不推荐
3. Vite 代理(开发环境推荐)⭐
利用 Vite 开发服务器的代理功能,将请求转发到后端服务器。
优点:
- 无需修改后端代码
- 开发环境专用,不影响生产环境
- 配置简单,功能强大
- 可以处理路径重写、请求头修改等
Vite 代理配置详解
基础配置
在 vite.config.ts 中配置 server.proxy:
typescript
import { defineConfig } from 'vite'
export default defineConfig({
server: {
// 端口号
port: 5173,
// 允许外部访问(局域网访问)
host: "0.0.0.0",
// 代理配置
proxy: {
// 代理所有以 /api 开头的请求
"/api": {
// 目标服务器地址
target: "http://后端地址",
// 改变请求头中的 origin,确保后端能正确识别来源
changeOrigin: true,
// 路径重写:去掉 /api 前缀
rewrite: (path) => path.replace(/^\/api/, "")
}
}
}
})
配置项说明
target
- 类型 :
string - 说明:后端服务器的实际地址
- 示例 :
"http://后端地址"
changeOrigin
- 类型 :
boolean - 默认值 :
false - 说明 :是否改变请求头中的
origin字段 - 作用 :当设置为
true时,请求头中的origin会被设置为target的值,这样可以避免后端因 origin 不匹配而拒绝请求 - 注意:此时更改http中的baseURL为'/api'
rewrite
- 类型 :
(path: string) => string - 说明:路径重写函数
- 作用:可以修改请求路径,例如去掉前缀、添加前缀等
示例:
typescript
rewrite: (path) => path.replace(/^\/api/, "")
// 请求 /api/login → 实际请求 http://后端地址/login
完整配置示例
typescript
// vite.config.ts
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
server: {
port: Number(env.VITE_PORT) || 5173,
host: "0.0.0.0",
proxy: {
"/api": {
target: env.VITE_API_BASE_URL || "后端地址",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
// 可选:配置 WebSocket 代理
ws: true,
// 可选:自定义请求头
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req, res) => {
// 可以在这里修改请求头
console.log('代理请求:', req.url)
})
}
}
},
// CORS 配置(可选,通常不需要)
cors: {
origin: "*",
credentials: true
}
}
}
})
前端 HTTP 客户端配置
配置好代理后,需要在前端 HTTP 客户端中设置正确的 baseURL:
Axios 配置示例
typescript
// src/utils/http/index.ts
import Axios, { type AxiosRequestConfig } from 'axios'
const defaultConfig: AxiosRequestConfig = {
timeout: 20000,
// 使用相对路径,Vite 会自动代理到后端
baseURL: "/api",
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest"
}
}
const axiosInstance = Axios.create(defaultConfig)
// 使用示例
export const http = {
get: <T>(url: string, config?: AxiosRequestConfig) => {
return axiosInstance.get<T>(url, config)
},
post: <T>(url: string, data?: any, config?: AxiosRequestConfig) => {
return axiosInstance.post<T>(url, data, config)
}
}
请求流程
-
前端发起请求:
typescripthttp.post("/login", { username: "admin", password: "123456" }) -
实际请求路径:
bashhttp://localhost:5173/api/login -
Vite 代理转发:
bashhttp://后端地址/login (去掉了 /api 前缀) -
后端响应:
响应原路返回 → Vite 代理 → 前端
高级配置场景
1. 多个代理规则
当需要代理多个不同的后端服务时:
typescript
proxy: {
"/api": {
target: "http://api.example.com",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, "")
},
"/upload": {
target: "http://upload.example.com",
changeOrigin: true
}
}
2. 使用正则表达式匹配
typescript
proxy: {
// 匹配所有以 /api 或 /v1 开头的请求
"^/api|^/v1": {
target: "http://2.2.50.2:28082",
changeOrigin: true
}
}
3. 代理 WebSocket
typescript
proxy: {
"/api": {
target: "ws://后端地址",
ws: true, // 启用 WebSocket 代理
changeOrigin: true
}
}
4. 自定义请求头
typescript
proxy: {
"/api": {
target: "http://后端地址",
changeOrigin: true,
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req, res) => {
// 添加自定义请求头
proxyReq.setHeader('X-Custom-Header', 'custom-value')
})
}
}
}
常见问题排查
1. 代理不生效
检查项:
- ✅ 确认
vite.config.ts配置正确 - ✅ 重启 Vite 开发服务器
- ✅ 检查
baseURL是否以/api开头 - ✅ 查看浏览器 Network 面板,确认请求是否发送到正确的地址
2. 请求 404
可能原因:
rewrite配置不正确,路径被错误重写target地址不正确- 后端路由不存在
解决方案:
typescript
// 添加日志查看实际请求路径
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('代理请求路径:', proxyReq.path)
})
}
3. Cookie 丢失
原因:跨域请求默认不携带 Cookie
解决方案:
typescript
proxy: {
"/api": {
target: "http://2.2.50.2:28082",
changeOrigin: true,
// 确保 Cookie 被正确传递
cookieDomainRewrite: "",
cookiePathRewrite: ""
}
}
4. 生产环境配置
重要:Vite 的代理功能仅在开发环境生效,生产环境需要:
-
使用 Nginx 反向代理:
nginxlocation /api { proxy_pass http://2.2.50.2:28082; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } -
或后端配置 CORS:
javascript// 允许所有源(生产环境建议指定具体域名) app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || '*', credentials: true }))
最佳实践
1. 使用环境变量
typescript
// .env.development
VITE_API_BASE_URL=http://后端地址
VITE_PORT=5173
// vite.config.ts
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
server: {
proxy: {
"/api": {
target: env.VITE_API_BASE_URL,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, "")
}
}
}
}
})
2. 类型安全
typescript
// 定义 API 响应类型
export interface ApiResponse<T> {
code: number
msg: string
data: T
}
// 使用示例
const response = await http.post<ApiResponse<UserInfo>>("/login", {
username: "admin",
password: "123456"
})
3. 错误处理
typescript
axiosInstance.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response) {
// 服务器返回错误
console.error('服务器错误:', error.response.status)
} else if (error.request) {
// 请求已发送但没有收到响应
console.error('网络错误:', error.request)
} else {
// 请求配置错误
console.error('请求错误:', error.message)
}
return Promise.reject(error)
}
)
总结
Vite 的代理功能是解决开发环境跨域问题的最佳方案:
✅ 无需修改后端代码
✅ 配置简单,功能强大
✅ 仅影响开发环境,不影响生产环境
✅ 支持路径重写、请求头修改等高级功能
通过合理配置 Vite 代理,可以大大提升前端开发效率,避免跨域问题带来的困扰。
参考文档
希望这篇文章能帮助你解决跨域问题!如果还有疑问,欢迎在评论区讨论。 🚀