178 lines
6.3 KiB
TypeScript
178 lines
6.3 KiB
TypeScript
import { defineConfig } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
import svgr from "vite-plugin-svgr";
|
|
|
|
// https://vite.dev/config/
|
|
export default defineConfig(({ mode }) => {
|
|
const isDev = mode === "development";
|
|
|
|
return {
|
|
plugins: [
|
|
react(),
|
|
svgr({
|
|
svgrOptions: {
|
|
icon: true,
|
|
// This will transform your SVG to a React component
|
|
exportType: "named",
|
|
namedExport: "ReactComponent",
|
|
},
|
|
}),
|
|
],
|
|
// Optimize dependency pre-bundling
|
|
optimizeDeps: {
|
|
include: [
|
|
// Only pre-bundle frequently used, small dependencies
|
|
'clsx',
|
|
'tailwind-merge',
|
|
'zustand',
|
|
// Include apexcharts for proper module resolution
|
|
'apexcharts',
|
|
'react-apexcharts',
|
|
],
|
|
// Exclude heavy dependencies that are only used in specific pages
|
|
// They will be lazy-loaded when needed
|
|
exclude: [
|
|
'@fullcalendar/core',
|
|
'@fullcalendar/daygrid',
|
|
'@fullcalendar/interaction',
|
|
'@fullcalendar/list',
|
|
'@fullcalendar/react',
|
|
'@fullcalendar/timegrid',
|
|
'@react-jvectormap/core',
|
|
'@react-jvectormap/world',
|
|
'react-dnd',
|
|
'react-dnd-html5-backend',
|
|
'swiper',
|
|
],
|
|
esbuildOptions: {
|
|
target: 'es2020',
|
|
},
|
|
},
|
|
// Build configuration for code splitting
|
|
build: {
|
|
// Enable minification (esbuild is faster than terser)
|
|
minify: 'esbuild',
|
|
// Enable CSS code splitting
|
|
cssCodeSplit: true,
|
|
// Optimize chunk size
|
|
rollupOptions: {
|
|
output: {
|
|
// Manual chunk splitting for better code splitting
|
|
manualChunks: (id) => {
|
|
// Vendor chunks - separate large dependencies for better caching
|
|
if (id.includes('node_modules')) {
|
|
// React core (most critical, always needed)
|
|
if (id.includes('react/') || id.includes('react-dom/')) {
|
|
return 'vendor-react-core';
|
|
}
|
|
// React Router (separate chunk - only loads on navigation)
|
|
if (id.includes('react-router')) {
|
|
return 'vendor-react-router';
|
|
}
|
|
// Heavy chart libraries (only used in specific pages)
|
|
if (id.includes('apexcharts') || id.includes('react-apexcharts')) {
|
|
return 'vendor-charts';
|
|
}
|
|
// Calendar libraries (only used in Calendar page)
|
|
if (id.includes('@fullcalendar')) {
|
|
return 'vendor-calendar';
|
|
}
|
|
// Map libraries (only used in specific pages)
|
|
if (id.includes('@react-jvectormap')) {
|
|
return 'vendor-maps';
|
|
}
|
|
// Drag and drop (only used in specific pages)
|
|
if (id.includes('react-dnd')) {
|
|
return 'vendor-dnd';
|
|
}
|
|
// Swiper (only used in specific pages)
|
|
if (id.includes('swiper')) {
|
|
return 'vendor-swiper';
|
|
}
|
|
// UI libraries (Radix UI, etc.)
|
|
if (id.includes('@radix-ui') || id.includes('framer-motion')) {
|
|
return 'vendor-ui';
|
|
}
|
|
// Zustand (state management - used everywhere)
|
|
if (id.includes('zustand')) {
|
|
return 'vendor-state';
|
|
}
|
|
// React Helmet (SEO)
|
|
if (id.includes('react-helmet')) {
|
|
return 'vendor-helmet';
|
|
}
|
|
// Other vendors (smaller libraries)
|
|
return 'vendor-other';
|
|
}
|
|
// Page chunks - each page gets its own chunk
|
|
if (id.includes('/pages/')) {
|
|
const match = id.match(/\/pages\/([^/]+)/);
|
|
if (match) {
|
|
const pageName = match[1];
|
|
// Group by module for better caching
|
|
if (pageName === 'Planner' || id.includes('/Planner/')) {
|
|
return 'pages-planner';
|
|
}
|
|
if (pageName === 'Writer' || id.includes('/Writer/')) {
|
|
return 'pages-writer';
|
|
}
|
|
if (pageName === 'Thinker' || id.includes('/Thinker/')) {
|
|
return 'pages-thinker';
|
|
}
|
|
if (pageName === 'Settings' || id.includes('/Settings/')) {
|
|
return 'pages-settings';
|
|
}
|
|
if (pageName === 'Billing' || id.includes('/Billing/')) {
|
|
return 'pages-billing';
|
|
}
|
|
// Individual page chunks for others
|
|
return `page-${pageName.toLowerCase()}`;
|
|
}
|
|
}
|
|
// Split icons into separate chunk (lazy load)
|
|
if (id.includes('/icons/') && id.endsWith('.svg')) {
|
|
return 'icons';
|
|
}
|
|
},
|
|
// Optimize chunk file names
|
|
chunkFileNames: 'assets/js/[name]-[hash].js',
|
|
entryFileNames: 'assets/js/[name]-[hash].js',
|
|
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
|
|
},
|
|
},
|
|
// Increase chunk size warning limit (default is 500kb)
|
|
chunkSizeWarningLimit: 600,
|
|
// Enable source maps in dev only
|
|
sourcemap: isDev,
|
|
// Report compressed sizes
|
|
reportCompressedSize: true,
|
|
},
|
|
// Only configure server and HMR in development mode
|
|
...(isDev && {
|
|
server: {
|
|
host: "0.0.0.0", // Allow external connections (for Docker)
|
|
port: 5173,
|
|
strictPort: false, // Allow port fallback if 5173 is busy
|
|
allowedHosts: [
|
|
"app.igny8.com",
|
|
"localhost",
|
|
"127.0.0.1",
|
|
],
|
|
watch: {
|
|
usePolling: true, // Needed for file watching in Docker
|
|
},
|
|
hmr: {
|
|
// Behind reverse proxy - use same origin strategy
|
|
// Client connects via public domain (app.igny8.com) on default HTTPS port (443)
|
|
// Caddy automatically proxies WebSocket upgrades from 443 to 5173
|
|
protocol: "wss",
|
|
// Don't specify host/port - Vite will use same origin as page
|
|
// This ensures client connects to wss://app.igny8.com (port 443 implicit)
|
|
},
|
|
// Increase timeout for slow connections and dependency pre-bundling
|
|
timeout: 120000, // 120 seconds (2 minutes) to match Caddy timeout
|
|
},
|
|
}),
|
|
};
|
|
});
|