feat: add environment configuration files and update API base URL handling for production
This commit is contained in:
2
.env.development.template
Normal file
2
.env.development.template
Normal file
@@ -0,0 +1,2 @@
|
||||
# Development Environment Variables
|
||||
VITE_API_BASE_URL=http://localhost:8000
|
||||
3
.env.production.template
Normal file
3
.env.production.template
Normal file
@@ -0,0 +1,3 @@
|
||||
# Production Environment Variables
|
||||
# In production with reverse proxy, we use relative URLs (same origin)
|
||||
# No API base URL needed - the reverse proxy handles /api routing
|
||||
@@ -6,6 +6,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite --port 8001",
|
||||
"build": "tsc -b && vite build",
|
||||
"build:production": "tsc -b && vite build --mode production",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { ThemeProviderContext, type Theme } from '@/contexts/ThemeContext'
|
||||
|
||||
type ThemeProviderProps = {
|
||||
@@ -49,3 +49,12 @@ export function ThemeProvider({
|
||||
</ThemeProviderContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export const useTheme = () => {
|
||||
const context = useContext(ThemeProviderContext)
|
||||
|
||||
if (context === undefined)
|
||||
throw new Error('useTheme must be used within a ThemeProvider')
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
ArrowRight,
|
||||
ArrowRightToLine
|
||||
} from 'lucide-react'
|
||||
import { playerService, type PlayerState, type PlayerMode } from '@/lib/api/services/player'
|
||||
import { playerService, type PlayerState, type PlayerMode, type MessageResponse } from '@/lib/api/services/player'
|
||||
import { filesService } from '@/lib/api/services/files'
|
||||
import { playerEvents, PLAYER_EVENTS } from '@/lib/events'
|
||||
import { toast } from 'sonner'
|
||||
@@ -79,7 +79,7 @@ export function Player({ className }: PlayerProps) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const executeAction = useCallback(async (action: () => Promise<void>, actionName: string) => {
|
||||
const executeAction = useCallback(async (action: () => Promise<void | MessageResponse>, actionName: string) => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
await action()
|
||||
|
||||
@@ -27,7 +27,12 @@ export function SocketProvider({ children }: SocketProviderProps) {
|
||||
const createSocket = useCallback(() => {
|
||||
if (!user) return null
|
||||
|
||||
const newSocket = io('http://localhost:8000', {
|
||||
// Get socket URL - use relative URL in production with reverse proxy
|
||||
const socketUrl = import.meta.env.PROD
|
||||
? '' // Use relative URL in production (same origin as frontend)
|
||||
: (import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000')
|
||||
|
||||
const newSocket = io(socketUrl, {
|
||||
withCredentials: true,
|
||||
transports: ['polling', 'websocket'],
|
||||
timeout: 20000,
|
||||
|
||||
@@ -12,7 +12,15 @@ export class BaseApiClient implements ApiClient {
|
||||
}
|
||||
|
||||
private buildURL(endpoint: string, params?: Record<string, string | number | boolean | undefined>): string {
|
||||
const url = new URL(endpoint, this.baseURL)
|
||||
let url: URL
|
||||
|
||||
if (this.baseURL) {
|
||||
// Full base URL provided
|
||||
url = new URL(endpoint, this.baseURL)
|
||||
} else {
|
||||
// Use relative URL (for reverse proxy)
|
||||
url = new URL(endpoint, window.location.origin)
|
||||
}
|
||||
|
||||
if (params) {
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
@@ -22,7 +30,7 @@ export class BaseApiClient implements ApiClient {
|
||||
})
|
||||
}
|
||||
|
||||
return url.toString()
|
||||
return this.baseURL ? url.toString() : url.pathname + url.search
|
||||
}
|
||||
|
||||
private async request<T>(
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
// API Configuration
|
||||
const getApiBaseUrl = () => {
|
||||
// If VITE_API_BASE_URL is explicitly set to empty string, use relative URLs
|
||||
if (import.meta.env.VITE_API_BASE_URL === '') {
|
||||
return '' // Use relative URLs (reverse proxy handles routing)
|
||||
}
|
||||
// In production with reverse proxy, use relative URL (same origin)
|
||||
if (import.meta.env.PROD) {
|
||||
return '' // Use relative URLs in production (reverse proxy handles routing)
|
||||
}
|
||||
// Use environment variable in development, fallback to localhost
|
||||
return import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
|
||||
}
|
||||
|
||||
export const API_CONFIG = {
|
||||
BASE_URL: 'http://localhost:8000',
|
||||
BASE_URL: getApiBaseUrl(),
|
||||
TIMEOUT: 30000, // 30 seconds
|
||||
RETRY_ATTEMPTS: 1,
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { apiClient } from '../client'
|
||||
import { API_CONFIG } from '../config'
|
||||
|
||||
export class FilesService {
|
||||
|
||||
@@ -11,4 +11,11 @@ export default defineConfig({
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
// Production build optimization
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: false, // Disable source maps in production for security
|
||||
},
|
||||
// For reverse proxy deployment, ensure assets are served from root
|
||||
base: '/',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user