Параметр server.proxy используется для настройки
проксирования HTTP-запросов во время работы dev-сервера Vite. Механизм
позволяет перенаправлять запросы с frontend-приложения на
backend-сервер, скрывать реальные адреса API, обходить ограничения CORS
и организовывать локальную разработку без изменения клиентского
кода.
Без прокси frontend обычно обращается к API напрямую:
fetch('http://localhost:3000/api/users')
Такой подход создаёт ряд проблем:
server.proxy решает эти задачи за счёт промежуточного
проксирующего слоя внутри dev-сервера Vite.
Простейшая конфигурация выглядит следующим образом:
import { defineConfig } from 'vite'
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000'
}
}
}
})
Теперь запрос:
fetch('/api/users')
будет автоматически перенаправлен на:
http://localhost:3000/api/users
Frontend при этом продолжает работать через Vite, например:
http://localhost:5173
Последовательность обработки:
/api), запрос
перенаправляется.Схема:
Browser
↓
Vite Dev Server
↓
Backend API
Наиболее распространённый сценарий:
proxy: {
'/api': {
target: 'http://localhost:8080'
}
}
Frontend:
axios.get('/api/posts')
Backend получает:
GET http://localhost:8080/api/posts
changeOriginНекоторые backend-серверы проверяют заголовок Host. Для
корректной работы используется changeOrigin.
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
changeOriginБез него:
Host: localhost:5173
С ним:
Host: localhost:8080
Это особенно важно при работе с:
rewriteИногда backend не ожидает префикс /api.
Например:
Frontend:
/api/users
Backend ожидает:
/users
Используется rewrite:
proxy: {
'/api': {
target: 'http://localhost:3000',
rewrite: (path) => path.replace(/^\/api/, '')
}
}
Теперь:
/api/users
станет:
/users
import { defineConfig } from 'vite'
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
secureИспользуется при работе с HTTPS.
secure: false
Позволяет игнорировать ошибки SSL-сертификатов.
Особенно полезно:
Пример:
proxy: {
'/api': {
target: 'https://localhost:8443',
secure: false
}
}
Vite поддерживает несколько прокси одновременно.
proxy: {
'/api': {
target: 'http://localhost:3000'
},
'/auth': {
target: 'http://localhost:4000'
},
'/files': {
target: 'http://localhost:5000'
}
}
Маршрутизация:
| Путь | Сервер |
|---|---|
/api/* |
localhost:3000 |
/auth/* |
localhost:4000 |
/files/* |
localhost:5000 |
Vite умеет проксировать WebSocket-соединения.
proxy: {
'/socket': {
target: 'ws://localhost:8080',
ws: true
}
}
Подключение:
const socket = new WebSocket('ws://localhost:5173/socket')
Vite автоматически перенаправит соединение.
proxy: {
'/socket': {
target: 'wss://localhost:8443',
ws: true,
secure: false
}
}
configureОпция configure предоставляет доступ к экземпляру
proxy.
proxy: {
'/api': {
target: 'http://localhost:3000',
configure: (proxy, options) => {
proxy.on('proxyReq', (proxyReq, req) => {
console.log(req.url)
})
}
}
}
Через неё можно:
proxy: {
'/api': {
target: 'http://localhost:3000',
configure: (proxy) => {
proxy.on('proxyReq', (proxyReq) => {
proxyReq.setHeader('X-Dev-Proxy', 'vite')
})
}
}
}
proxy: {
'/api': {
target: 'http://localhost:3000',
configure: (proxy) => {
proxy.on('error', (err) => {
console.error(err)
})
}
}
}
Адрес backend можно выбирать через переменные окружения.
VITE_API_URL=http://localhost:3000
Конфигурация:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
server: {
proxy: {
'/api': {
target: env.VITE_API_URL,
changeOrigin: true
}
}
}
}
})
Важно понимать:
server.proxy работает только в dev-режиме.
Во время production-сборки Vite не запускает dev server, поэтому прокси отсутствует.
Обычно используются:
Пример nginx:
location /api {
proxy_pass http://backend:3000;
}
Без прокси:
localhost:5173 → localhost:3000
Браузер считает это разными origin.
Возникают ошибки:
Access-Control-Allow-Origin
С прокси:
localhost:5173 → localhost:5173/api
Для браузера запрос остаётся same-origin.
import axios from 'axios'
const api = axios.create({
baseURL: '/api'
})
Запрос:
api.get('/users')
fetch('/api/posts')
При использовании авторизации важно корректно проксировать cookies.
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
В большинстве случаев этого достаточно для работы:
Иногда backend возвращает cookies с неправильным доменом.
Используется:
cookieDomainRewrite: 'localhost'
Пример:
proxy: {
'/api': {
target: 'http://localhost:3000',
cookieDomainRewrite: 'localhost'
}
}
cookiePathRewrite: '/'
proxy: {
'/graphql': {
target: 'http://localhost:4000',
changeOrigin: true
}
}
Запросы:
fetch('/graphql', {
method: 'POST'
})
Частая конфигурация:
proxy: {
'/api': {
target: 'http://backend:3000'
}
}
где:
backend
— имя Docker-контейнера.
Если Vite запускается через HTTPS:
server: {
https: true
}
прокси продолжает работать аналогично.
Вместо строки можно использовать регулярные выражения.
proxy: {
'^/fallback/.*': {
target: 'http://localhost:3000'
}
}
Иногда используется глобальный proxy:
proxy: {
'/': {
target: 'http://localhost:3000'
}
}
Но такой подход опасен:
Более безопасный вариант:
proxy: {
'/api': {
target: 'http://localhost:3000'
}
}
proxy: {
'/api': 'http://localhost:3000'
}
Это сокращённая форма.
Полный объект предпочтительнее, поскольку поддерживает:
Полезные способы диагностики:
console.log(import.meta.env)
configure: (proxy) => {
proxy.on('proxyReq', (proxyReq, req) => {
console.log(req.method, req.url)
})
}
curl http://localhost:3000/api/users
target: 'localhost:3000'
Ошибка:
Must provide a proper URL
Правильно:
target: 'http://localhost:3000'
Frontend:
https://localhost:5173
Backend:
http://localhost:3000
Некоторые браузеры могут блокировать mixed content.
Частая ошибка — ожидание, что vite build сохранит
proxy.
server.proxy относится только к dev server.
Ошибка:
rewrite: path.replace('/api', '')
Правильно:
rewrite: (path) => path.replace(/^\/api/, '')
Рекомендуется:
/api
или:
/backend
Это упрощает:
Плохо:
fetch('http://localhost:3000/api/users')
Хорошо:
fetch('/api/users')
export const API_URL = '/api'
Прокси работает параллельно с системой Hot Module Replacement.
Vite разделяет:
Поэтому корректно настроенный proxy не мешает обновлению модулей.
target: 'http://localhost:3000'
target: 'http://localhost:4000'
target: 'http://localhost:8000'
target: 'http://localhost:8000'
target: 'http://localhost:8080'
Vite использует библиотеку:
http-proxy
Через неё реализуются:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd())
return {
server: {
host: true,
port: 5173,
proxy: {
'/api': {
target: env.VITE_API_URL,
changeOrigin: true,
secure: false,
rewrite: (path) => {
return path.replace(/^\/api/, '')
},
configure: (proxy) => {
proxy.on('proxyReq', (proxyReq, req) => {
console.log(
'[PROXY]',
req.method,
req.url
)
})
proxy.on('error', (err) => {
console.error(err)
})
}
},
'/socket': {
target: env.VITE_WS_URL,
ws: true,
changeOrigin: true
}
}
}
}
})