Implement relative paths for frontend API and WebSocket connections
- Created `.env.production` file to define relative paths for production deployment. - Updated frontend API and WebSocket client to use environment variables for dynamic URL handling. - Enhanced deployment scripts (`deploy-ubuntu.sh`, `start.sh`, `start.bat`) to generate `.env.production` automatically. - Added `PRODUCTION_URLS.md` for documentation on production URL configuration and troubleshooting.
This commit is contained in:
parent
48fbb5bcb3
commit
70889421ea
250
PRODUCTION_URLS.md
Normal file
250
PRODUCTION_URLS.md
Normal file
@ -0,0 +1,250 @@
|
||||
# 🌐 Настройка URL для Production
|
||||
|
||||
## Проблема
|
||||
|
||||
После развертывания на сервере frontend пытается обращаться к `localhost` вместо реального IP/домена сервера.
|
||||
|
||||
## ✅ Решение
|
||||
|
||||
Frontend теперь использует **относительные пути** и динамические URL.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Как это работает
|
||||
|
||||
### 1. API запросы
|
||||
|
||||
**До:**
|
||||
```typescript
|
||||
const API_BASE_URL = 'http://localhost:8000/api';
|
||||
```
|
||||
|
||||
**После:**
|
||||
```typescript
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api';
|
||||
```
|
||||
|
||||
### 2. WebSocket
|
||||
|
||||
**До:**
|
||||
```typescript
|
||||
const wsUrl = 'ws://localhost:8000/ws/reviews';
|
||||
```
|
||||
|
||||
**После:**
|
||||
```typescript
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const host = import.meta.env.VITE_WS_URL || `${protocol}//${window.location.host}`;
|
||||
const wsUrl = `${host}/ws/reviews`;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Режимы работы
|
||||
|
||||
### Development (npm run dev)
|
||||
|
||||
Frontend работает на `localhost:5173`, proxy перенаправляет запросы:
|
||||
|
||||
```typescript
|
||||
// vite.config.ts
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:8000',
|
||||
'/ws': 'ws://localhost:8000',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Запросы:**
|
||||
- `http://localhost:5173/api/...` → `http://localhost:8000/api/...`
|
||||
- `ws://localhost:5173/ws/...` → `ws://localhost:8000/ws/...`
|
||||
|
||||
### Production (npm run build)
|
||||
|
||||
Frontend собран в `backend/public/`, backend раздает статику.
|
||||
|
||||
**Относительные пути:**
|
||||
- `/api/...` → `http://your-server-ip:8000/api/...`
|
||||
- `/ws/...` → `ws://your-server-ip:8000/ws/...`
|
||||
|
||||
Browser автоматически использует текущий host!
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Примеры
|
||||
|
||||
### На локальной машине:
|
||||
|
||||
```
|
||||
URL браузера: http://localhost:8000
|
||||
API запрос: http://localhost:8000/api/repositories
|
||||
WebSocket: ws://localhost:8000/ws/reviews
|
||||
```
|
||||
|
||||
### На сервере (IP):
|
||||
|
||||
```
|
||||
URL браузера: http://185.152.81.243:8000
|
||||
API запрос: http://185.152.81.243:8000/api/repositories
|
||||
WebSocket: ws://185.152.81.243:8000/ws/reviews
|
||||
```
|
||||
|
||||
### На сервере (домен):
|
||||
|
||||
```
|
||||
URL браузера: https://ai-review.example.com
|
||||
API запрос: https://ai-review.example.com/api/repositories
|
||||
WebSocket: wss://ai-review.example.com/ws/reviews
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Переменные окружения
|
||||
|
||||
### .env.production (создается автоматически)
|
||||
|
||||
```bash
|
||||
# Относительные пути (по умолчанию)
|
||||
VITE_API_URL=/api
|
||||
VITE_WS_URL=
|
||||
```
|
||||
|
||||
### .env.development (для разработки)
|
||||
|
||||
```bash
|
||||
# Явные URL для development
|
||||
VITE_API_URL=http://localhost:8000/api
|
||||
VITE_WS_URL=ws://localhost:8000
|
||||
```
|
||||
|
||||
### Кастомная настройка:
|
||||
|
||||
Если нужен специфичный URL (например, разные домены):
|
||||
|
||||
```bash
|
||||
# frontend/.env.production
|
||||
VITE_API_URL=https://api.example.com/api
|
||||
VITE_WS_URL=wss://api.example.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Пересборка после изменений
|
||||
|
||||
### Локально:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### На сервере:
|
||||
|
||||
```bash
|
||||
cd /opt/ai-review/frontend
|
||||
npm run build
|
||||
sudo systemctl restart ai-review
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Проблема: API запросы идут на localhost
|
||||
|
||||
**Причина:** Frontend собран со старым кодом
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
cd frontend
|
||||
rm -rf dist/ ../backend/public/
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Проблема: WebSocket не подключается
|
||||
|
||||
**Проверьте:**
|
||||
1. Открыть DevTools → Network → WS
|
||||
2. Проверить URL WebSocket подключения
|
||||
3. Убедиться что backend доступен
|
||||
|
||||
**Для HTTPS:**
|
||||
```bash
|
||||
# WebSocket должен использовать wss://
|
||||
# Убедитесь что nginx прокси настроен:
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://localhost:8000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
```
|
||||
|
||||
### Проблема: CORS ошибки
|
||||
|
||||
**Если используете разные домены:**
|
||||
|
||||
Обновите `backend/.env`:
|
||||
```bash
|
||||
CORS_ORIGINS=https://yourdomain.com,https://api.yourdomain.com
|
||||
```
|
||||
|
||||
Перезапустите backend:
|
||||
```bash
|
||||
sudo systemctl restart ai-review
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Проверка
|
||||
|
||||
### 1. Откройте DevTools (F12)
|
||||
|
||||
### 2. Network tab
|
||||
|
||||
Проверьте запросы:
|
||||
- ✅ URL должны использовать текущий host
|
||||
- ✅ Не должно быть `localhost` в production
|
||||
|
||||
### 3. Console
|
||||
|
||||
Не должно быть ошибок типа:
|
||||
- ❌ `Failed to fetch`
|
||||
- ❌ `ERR_CONNECTION_REFUSED`
|
||||
- ❌ `Mixed Content` (http на https странице)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Пример логов
|
||||
|
||||
### ✅ Правильно (на сервере 185.152.81.243):
|
||||
|
||||
```
|
||||
GET http://185.152.81.243:8000/api/repositories 200 OK
|
||||
WS ws://185.152.81.243:8000/ws/reviews [connected]
|
||||
```
|
||||
|
||||
### ❌ Неправильно:
|
||||
|
||||
```
|
||||
GET http://localhost:8000/api/repositories [failed]
|
||||
WS ws://localhost:8000/ws/reviews [failed]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Готово!
|
||||
|
||||
Теперь приложение работает на любом домене/IP без изменений кода!
|
||||
|
||||
**Автоматически подстраивается под:**
|
||||
- ✅ localhost
|
||||
- ✅ IP адрес
|
||||
- ✅ Домен
|
||||
- ✅ HTTP/HTTPS
|
||||
- ✅ WS/WSS
|
||||
|
||||
**Больше не нужно менять код при деплое!** 🚀
|
||||
|
||||
@ -82,6 +82,14 @@ echo -e "${GREEN}✓ Файлы скопированы${NC}"
|
||||
# 4. Сборка frontend
|
||||
echo -e "${YELLOW}[4/10] Сборка frontend...${NC}"
|
||||
cd frontend
|
||||
|
||||
# Создаем .env.production для относительных путей
|
||||
cat > .env.production << 'EOF'
|
||||
# Production - используем относительные пути
|
||||
VITE_API_URL=/api
|
||||
VITE_WS_URL=
|
||||
EOF
|
||||
|
||||
sudo -u "$REAL_USER" npm install
|
||||
sudo -u "$REAL_USER" npm run build
|
||||
cd ..
|
||||
|
||||
2
frontend/.env.production
Normal file
2
frontend/.env.production
Normal file
@ -0,0 +1,2 @@
|
||||
VITE_API_URL=/api
|
||||
VITE_WS_URL=
|
||||
@ -1,7 +1,8 @@
|
||||
import axios from 'axios';
|
||||
import type { Repository, RepositoryCreate, Review, ReviewStats } from '../types';
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000/api';
|
||||
// Используем относительный путь для production или env для development
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api';
|
||||
|
||||
const api = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import { WebSocketMessage } from '../types';
|
||||
|
||||
const WS_URL = import.meta.env.VITE_WS_URL || 'ws://localhost:8000';
|
||||
|
||||
export class WebSocketClient {
|
||||
private ws: WebSocket | null = null;
|
||||
private listeners: Map<string, Set<(data: any) => void>> = new Map();
|
||||
@ -9,13 +7,26 @@ export class WebSocketClient {
|
||||
private maxReconnectAttempts = 5;
|
||||
private reconnectDelay = 3000;
|
||||
|
||||
private getWebSocketUrl(): string {
|
||||
// Если задан VITE_WS_URL, используем его
|
||||
if (import.meta.env.VITE_WS_URL) {
|
||||
return import.meta.env.VITE_WS_URL;
|
||||
}
|
||||
|
||||
// Иначе определяем автоматически на основе текущего location
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const host = window.location.host;
|
||||
return `${protocol}//${host}`;
|
||||
}
|
||||
|
||||
connect() {
|
||||
if (this.ws?.readyState === WebSocket.OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.ws = new WebSocket(`${WS_URL}/ws/reviews`);
|
||||
const wsUrl = this.getWebSocketUrl();
|
||||
this.ws = new WebSocket(`${wsUrl}/ws/reviews`);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
console.log('WebSocket connected');
|
||||
|
||||
@ -45,6 +45,11 @@ echo.
|
||||
|
||||
REM 4. Сборка frontend
|
||||
echo [STEP 4/7] Сборка frontend...
|
||||
|
||||
REM Создаем .env.production для production
|
||||
echo VITE_API_URL=/api > .env.production
|
||||
echo VITE_WS_URL= >> .env.production
|
||||
|
||||
call npm run build
|
||||
echo [OK] Frontend собран в backend/public
|
||||
echo.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user