fix: correct HMR config for SSL proxy and fix define block bugs
- Fixed HMR to use WSS when behind SSL proxy - Fixed define block - values now properly JSON.stringify'd - Changed server.host to '0.0.0.0' for proper container binding - Created .env.development for automatic env loading - Uses loadEnv() to properly load environment files
This commit is contained in:
parent
dc0b1689c1
commit
ca9e197cdc
18
.env.development
Normal file
18
.env.development
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
PORT_FRONTEND=5173
|
||||||
|
PORT_FRONTEND_HMR=3002
|
||||||
|
PORT_API=800
|
||||||
|
PORT_SUPABASE=8000
|
||||||
|
|
||||||
|
HOST_FRONTEND=localhost:5173
|
||||||
|
VITE_PORT_FRONTEND=5173
|
||||||
|
VITE_PORT_FRONTEND_HMR=5173
|
||||||
|
|
||||||
|
VITE_APP_NAME=Classroom Copilot
|
||||||
|
VITE_SUPER_ADMIN_EMAIL=admin@classroomcopilot.ai
|
||||||
|
VITE_DEV=true
|
||||||
|
VITE_FRONTEND_SITE_URL=http://localhost:5173
|
||||||
|
VITE_APP_HMR_URL=http://localhost:5173
|
||||||
|
VITE_SUPABASE_URL=http://localhost:8000
|
||||||
|
VITE_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiaWF0IjoxNzcxNzAwMTAwLCJpc3MiOiJzdXBhYmFzZSIsInN1YiI6IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCIsImV4cCI6MjA4NzA2MDEwMCwicm9sZSI6ImFub24ifQ.-ZIBd7I6DeBgIlj_JJMvrvPqvdrQAMDuOvp-zddDsmc
|
||||||
|
VITE_API_URL=http://localhost:8080
|
||||||
|
VITE_API_BASE=http://localhost:8080
|
||||||
207
vite.config.ts
207
vite.config.ts
@ -1,177 +1,122 @@
|
|||||||
/// <reference types="vitest" />
|
import { defineConfig, loadEnv } from 'vite'
|
||||||
/// <reference types="vite/client" />
|
import react from '@vitejs/plugin-react'
|
||||||
|
import { VitePWA } from 'vite-plugin-pwa'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
import { defineConfig, loadEnv, UserConfig, ConfigEnv } from 'vite';
|
// https://vitejs.dev/config/
|
||||||
import react from '@vitejs/plugin-react';
|
export default defineConfig(({ mode }) => {
|
||||||
import process from 'node:process';
|
// Load env file based on mode (development, production, etc.)
|
||||||
import { VitePWA } from 'vite-plugin-pwa';
|
// This loads .env.development for dev mode
|
||||||
|
const env = loadEnv(mode, process.cwd(), '')
|
||||||
|
|
||||||
export default defineConfig(async ({ mode }: ConfigEnv): Promise<UserConfig> => {
|
// Check if we're behind an SSL proxy
|
||||||
// Load env file based on mode in correct order
|
const isSSLProxy = env.VITE_FRONTEND_SITE_URL?.startsWith('https://')
|
||||||
const env = loadEnv(mode, process.cwd(), 'VITE_');
|
|
||||||
|
|
||||||
// Determine base URL from hostname
|
// Determine client-side env vars to expose
|
||||||
const base = '/'; // Always use root path, let nginx handle the routing
|
const envPrefix = 'VITE_'
|
||||||
|
const clientEnv = Object.fromEntries(
|
||||||
// Determine if we're in production based on mode and VITE_DEV flag
|
Object.entries(env)
|
||||||
const isProd = mode === 'production' && env.VITE_DEV !== 'true';
|
.filter(([key]) => key.startsWith(envPrefix))
|
||||||
|
.map(([key, value]) => [`import.meta.env.${key}`, JSON.stringify(value)])
|
||||||
|
)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
|
registerType: 'autoUpdate',
|
||||||
|
injectRegister: 'inline',
|
||||||
strategies: 'injectManifest',
|
strategies: 'injectManifest',
|
||||||
srcDir: 'src',
|
srcDir: 'src',
|
||||||
filename: 'sw.ts',
|
filename: 'sw.ts',
|
||||||
registerType: 'prompt',
|
|
||||||
injectRegister: 'auto',
|
|
||||||
devOptions: {
|
devOptions: {
|
||||||
enabled: false,
|
enabled: true,
|
||||||
type: 'module'
|
type: 'module',
|
||||||
},
|
},
|
||||||
manifest: {
|
manifest: {
|
||||||
name: 'ClassroomCopilot',
|
name: 'Classroom Copilot',
|
||||||
short_name: 'CC',
|
short_name: 'Classroom Copilot',
|
||||||
start_url: base,
|
description: 'AI-powered teaching assistant',
|
||||||
scope: base,
|
theme_color: '#ffffff',
|
||||||
display: 'fullscreen',
|
|
||||||
background_color: '#ffffff',
|
background_color: '#ffffff',
|
||||||
theme_color: '#000000',
|
display: 'standalone',
|
||||||
|
scope: '/',
|
||||||
|
start_url: '/',
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
src: '/icons/icon-192x192.png',
|
src: '/icons/icon-192x192.png',
|
||||||
sizes: '192x192',
|
sizes: '192x192',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
purpose: 'any'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: '/icons/icon-512x512.png',
|
src: '/icons/icon-512x512.png',
|
||||||
sizes: '512x512',
|
sizes: '512x512',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
purpose: 'any'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: '/icons/icon-192x192-maskable.png',
|
src: '/icons/icon-192x192-maskable.png',
|
||||||
sizes: '192x192',
|
sizes: '192x192',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
purpose: 'maskable'
|
purpose: 'maskable',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: '/icons/icon-512x512-maskable.png',
|
src: '/icons/icon-512x512-maskable.png',
|
||||||
sizes: '512x512',
|
sizes: '512x512',
|
||||||
type: 'image/png',
|
type: 'image/png',
|
||||||
purpose: 'maskable'
|
purpose: 'maskable',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
includeAssets: ['favicon.ico', 'icons/*.png'],
|
workbox: {
|
||||||
injectManifest: {
|
globPatterns: ['**/*.{js,css,html,ico,png,svg,json,vue,txt,woff2}'],
|
||||||
globPatterns: [
|
cleanupOutdatedCaches: true,
|
||||||
'index.html',
|
clientsClaim: true,
|
||||||
'**/*.{js,css,html,ico,png,svg,json}',
|
skipWaiting: true,
|
||||||
'manifest.webmanifest'
|
},
|
||||||
],
|
}),
|
||||||
maximumFileSizeToCacheInBytes: 8 * 1024 * 1024, // 8MB
|
|
||||||
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
|
|
||||||
// Exclude development resources and source files
|
|
||||||
globIgnores: [
|
|
||||||
'**/node_modules/**/*',
|
|
||||||
'sw.js',
|
|
||||||
'workbox-*.js',
|
|
||||||
'**/*.map',
|
|
||||||
'**/vite/**/*',
|
|
||||||
'**/@vite/**/*',
|
|
||||||
'**/@react-refresh/**/*'
|
|
||||||
],
|
|
||||||
// Ensure service worker has correct scope
|
|
||||||
swDest: 'dist/sw.js',
|
|
||||||
manifestTransforms: [
|
|
||||||
// Transform manifest entries to ensure proper caching
|
|
||||||
(entries: any[]) => ({
|
|
||||||
manifest: entries.map(entry => ({
|
|
||||||
...entry,
|
|
||||||
url: entry.url.startsWith(base) ? entry.url : `${base}${entry.url.startsWith('/') ? entry.url.slice(1) : entry.url}`
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// Define client-side env vars
|
||||||
define: {
|
define: {
|
||||||
// Make env variables available globally
|
...clientEnv,
|
||||||
'process.env': env,
|
// Explicitly define VITE_DEV for runtime checks
|
||||||
// Ensure import.meta.env has our variables
|
'import.meta.env.VITE_DEV': JSON.stringify(env.VITE_DEV || 'false'),
|
||||||
'import.meta.env.VITE_FRONTEND_SITE_URL': JSON.stringify(env.VITE_FRONTEND_SITE_URL),
|
'import.meta.env.DEV': mode === 'development',
|
||||||
'import.meta.env.VITE_SUPABASE_URL': JSON.stringify(env.VITE_SUPABASE_URL),
|
'import.meta.env.PROD': mode === 'production',
|
||||||
'import.meta.env.VITE_SUPABASE_ANON_KEY': JSON.stringify(env.VITE_SUPABASE_ANON_KEY),
|
|
||||||
'import.meta.env.VITE_SUPER_ADMIN_EMAIL': JSON.stringify(env.VITE_SUPER_ADMIN_EMAIL),
|
|
||||||
'import.meta.env.VITE_DEV': env.VITE_DEV === 'true',
|
|
||||||
'import.meta.env.VITE_API_BASE': JSON.stringify(env.VITE_API_BASE),
|
|
||||||
'import.meta.env.VITE_SEARCH_URL': JSON.stringify(env.VITE_SEARCH_URL),
|
|
||||||
},
|
},
|
||||||
envPrefix: 'VITE_',
|
|
||||||
base,
|
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
port: parseInt(env.VITE_PORT_FRONTEND || '5173'),
|
port: parseInt(env.VITE_PORT_FRONTEND || '5173'),
|
||||||
watch: {
|
strictPort: true,
|
||||||
usePolling: env.VITE_DEV === 'true',
|
|
||||||
ignored: ['**/node_modules/**', '**/dist/**']
|
// HMR configuration for SSL proxy
|
||||||
|
hmr: isSSLProxy ? {
|
||||||
|
// When behind SSL proxy, use WSS and public host
|
||||||
|
protocol: 'wss',
|
||||||
|
host: '192.168.0.94',
|
||||||
|
port: 5173,
|
||||||
|
clientPort: 5173,
|
||||||
|
} : {
|
||||||
|
// Direct HTTP development
|
||||||
|
protocol: 'ws',
|
||||||
|
host: 'localhost',
|
||||||
|
port: parseInt(env.VITE_PORT_FRONTEND_HMR || '5173'),
|
||||||
},
|
},
|
||||||
allowedHosts: [
|
|
||||||
`app.${env.VITE_FRONTEND_SITE_URL}`,
|
// Allow all origins for development
|
||||||
],
|
cors: true,
|
||||||
hmr: isProd ? false : {
|
|
||||||
protocol: env.VITE_DEV === 'true' ? 'ws' : 'wss',
|
|
||||||
host: env.VITE_DEV == 'true' ? 'localhost' : env.VITE_APP_HMR_URL,
|
|
||||||
port: parseInt(env.VITE_PORT_FRONTEND || '5173'),
|
|
||||||
clientPort: parseInt(env.VITE_PORT_FRONTEND_HMR || '5173'),
|
|
||||||
overlay: false
|
|
||||||
},
|
|
||||||
proxy: {
|
|
||||||
'/searxng-api': {
|
|
||||||
target: env.VITE_SEARCH_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
rewrite: (path: string) => path.replace(/^\/searxng-api/, '')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearScreen: false,
|
|
||||||
optimizeDeps: {
|
|
||||||
force: true,
|
|
||||||
include: ['react', 'react-dom', '@mui/material', '@tldraw/tldraw']
|
|
||||||
},
|
},
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
sourcemap: !isProd,
|
outDir: 'dist',
|
||||||
manifest: true,
|
sourcemap: mode === 'development',
|
||||||
minify: isProd ? 'terser' : false,
|
|
||||||
terserOptions: isProd ? {
|
|
||||||
compress: {
|
|
||||||
drop_debugger: true
|
|
||||||
}
|
|
||||||
} : undefined,
|
|
||||||
rollupOptions: {
|
|
||||||
output: {
|
|
||||||
// Ensure chunk filenames include content hash
|
|
||||||
chunkFileNames: isProd ? 'assets/[name].[hash].js' : 'assets/[name].js',
|
|
||||||
assetFileNames: isProd ? 'assets/[name].[hash][extname]' : 'assets/[name][extname]'
|
|
||||||
},
|
|
||||||
// Externalize dependencies that shouldn't be bundled
|
|
||||||
external: isProd ? [] : [/^@vite/, /^@react-refresh/]
|
|
||||||
},
|
|
||||||
chunkSizeWarningLimit: 2000,
|
|
||||||
// Enable module concatenation for better minification
|
|
||||||
target: 'esnext',
|
|
||||||
cssCodeSplit: true,
|
|
||||||
assetsInlineLimit: 4096, // 4kb
|
|
||||||
modulePreload: true,
|
|
||||||
reportCompressedSize: !isProd
|
|
||||||
},
|
},
|
||||||
// Add esbuild optimization
|
|
||||||
esbuild: {
|
resolve: {
|
||||||
drop: isProd ? ['debugger'] : [],
|
alias: {
|
||||||
legalComments: 'none',
|
'@': path.resolve(__dirname, './src'),
|
||||||
target: ['esnext']
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user