Vite前端API调用与本地开发代理配置详解
一、基础API调用方式
1.1 使用原生Fetch API
// 基础GET请求
async function fetchData() {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error('请求失败:', error);
}
}
// POST请求示例
async function postData(url, data) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
return response.json();
}
1.2 使用Axios(推荐)
// 安装: npm install axios
import axios from 'axios';
// 创建实例
const api = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
// 请求拦截器
api.interceptors.request.use(
config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
// 响应拦截器
api.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
// 处理未授权
window.location.href = '/login';
}
return Promise.reject(error);
}
);
// 使用示例
export const userAPI = {
getUsers: () => api.get('/users'),
createUser: (data) => api.post('/users', data),
updateUser: (id, data) => api.put(`/users/${id}`, data),
};
二、Vite代理配置详解
2.1 基础代理配置
// vite.config.js / vite.config.ts
import { defineConfig } from 'vite';
export default defineConfig({
server: {
proxy: {
// 简单代理配置
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
2.2 多环境代理配置
// vite.config.js
export default defineConfig(({ mode }) => {
// 根据环境选择不同的代理配置
const proxyConfig = {
development: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
},
},
staging: {
'/api': {
target: 'https://staging-api.example.com',
changeOrigin: true,
},
},
production: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
},
},
};
return {
server: {
proxy: proxyConfig[mode] || proxyConfig.development,
},
};
});
2.3 高级代理配置示例
export default defineConfig({
server: {
proxy: {
// 多个API端点
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
// WebSocket代理
'/socket.io': {
target: 'ws://localhost:3001',
ws: true,
},
// 带身份验证的代理
'/auth': {
target: 'http://localhost:3002',
changeOrigin: true,
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req, res) => {
// 添加自定义请求头
proxyReq.setHeader('X-Special-Proxy-Header', 'vite-proxy');
});
},
},
// 路径前缀保留
'/external-api/v1': {
target: 'https://external-service.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/external-api/, '/api'),
},
},
},
});
三、环境变量配置
3.1 环境变量文件
# .env.development
VITE_API_BASE_URL=http://localhost:3000
VITE_APP_NAME=MyApp Dev
# .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_NAME=MyApp
3.2 TypeScript支持
// env.d.ts
interface ImportMetaEnv {
readonly VITE_API_BASE_URL: string;
readonly VITE_APP_NAME: string;
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
3.3 API服务封装
// src/services/api.ts
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
class APIService {
private axiosInstance: AxiosInstance;
constructor() {
this.axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 15000,
headers: {
'Content-Type': 'application/json',
},
});
this.setupInterceptors();
}
private setupInterceptors() {
// 请求拦截器
this.axiosInstance.interceptors.request.use(
config => this.handleRequest(config),
error => Promise.reject(error)
);
// 响应拦截器
this.axiosInstance.interceptors.response.use(
response => this.handleResponse(response),
error => this.handleError(error)
);
}
private handleRequest(config: AxiosRequestConfig) {
const token = localStorage.getItem('access_token');
if (token) {
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
};
}
return config;
}
private handleResponse(response: any) {
return response.data;
}
private handleError(error: any) {
if (error.response?.status === 401) {
// 刷新token逻辑
return this.refreshTokenAndRetry(error.config);
}
if (error.response?.status === 403) {
// 权限不足处理
window.location.href = '/403';
}
return Promise.reject(error);
}
// API方法
public get = (url: string, config?: AxiosRequestConfig) =>
this.axiosInstance.get(url, config);
public post = (url: string, data?: any, config?: AxiosRequestConfig) =>
this.axiosInstance.post(url, data, config);
// 其他HTTP方法...
}
export const apiService = new APIService();
四、实际项目架构示例
4.1 模块化API组织
src/
├── api/
│ ├── index.ts # API入口文件
│ ├── auth.ts # 认证相关API
│ ├── user.ts # 用户相关API
│ ├── product.ts # 产品相关API
│ └── types/ # TypeScript类型定义
│ ├── auth.ts
│ └── user.ts
├── services/
│ ├── api.ts # API服务基类
│ └── request.ts # 请求封装
└── utils/
└── http.ts # HTTP工具函数
4.2 类型安全的API调用
// src/api/types/user.ts
export interface User {
id: number;
name: string;
email: string;
avatar?: string;
}
export interface CreateUserDto {
name: string;
email: string;
password: string;
}
// src/api/user.ts
import { apiService } from '@/services/api';
import type { User, CreateUserDto } from './types/user';
export const userAPI = {
// 获取用户列表
getUsers: (params?: {
page?: number;
limit?: number;
search?: string;
}) => apiService.get<User[]>('/users', { params }),
// 创建用户
createUser: (data: CreateUserDto) =>
apiService.post<User>('/users', data),
// 获取用户详情
getUserById: (id: number) =>
apiService.get<User>(`/users/${id}`),
// 更新用户
updateUser: (id: number, data: Partial<CreateUserDto>) =>
apiService.put<User>(`/users/${id}`, data),
// 删除用户
deleteUser: (id: number) =>
apiService.delete(`/users/${id}`),
};
五、开发调试技巧
5.1 Mock数据开发
// vite.config.js
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [
// 使用vite-plugin-mock
require('vite-plugin-mock')({
mockPath: 'mock', // mock文件目录
enable: true, // 开发环境启用
}),
],
});
// mock/user.js
export default [
{
url: '/api/users',
method: 'get',
response: () => ({
code: 0,
data: [
{ id: 1, name: '张三', email: 'zhangsan@example.com' },
{ id: 2, name: '李四', email: 'lisi@example.com' },
],
}),
},
];
5.2 网络请求监控
// 全局请求监控
const originalFetch = window.fetch;
window.fetch = function(...args) {
const startTime = Date.now();
console.log(`🚀 请求开始: ${args[0]}`);
return originalFetch.apply(this, args).then(response => {
console.log(`✅ 请求完成: ${args[0]}, 耗时: ${Date.now() - startTime}ms`);
return response;
}).catch(error => {
console.error(`❌ 请求失败: ${args[0]}`, error);
throw error;
});
};
六、最佳实践总结
6.1 配置建议
环境隔离:区分开发、测试、生产环境的配置
类型安全:使用TypeScript确保API调用的类型安全
错误处理:统一的错误处理机制
请求拦截:添加loading状态、身份验证等通用逻辑
响应格式化:统一响应数据结构
6.2 性能优化
请求缓存:对不经常变化的数据进行缓存
请求取消:避免重复请求和竞态条件
分页加载:大数据列表使用分页
图片懒加载:优化图片资源加载
6.3 安全考虑
CSRF防护:添加CSRF token
XSS防护:对用户输入进行过滤
敏感信息:避免在客户端存储敏感信息
HTTPS:生产环境强制使用HTTPS
通过以上配置和策略,可以在Vite项目中实现高效、安全、易维护的API调用和代理配置。