Files
Maestro/vite.config.web.mts
Pedram Amini 3f1788d196 perf: Optimize AI input responsiveness and production builds
- Fix AI input lag by using local state for typing, syncing to session
  state only on blur/submit instead of every keystroke
- Add esbuild.drop to strip console.* and debugger in production builds
- Memoize handleInputFocus and handleSessionClick callbacks in MainPanel
- Simplify textarea auto-grow by removing unnecessary RAF scheduling
- Fix AgentSessionsBrowser by changing button to div (nested button issue)
- Restore legacy history filter fallback for entries without sessionId

Claude ID: 33f0f964-5b7f-4240-9e40-8eddcecafe8e
Maestro ID: b9bc0d08-5be2-4fdf-93cd-5618a8d53b35
2025-12-01 09:38:28 -06:00

162 lines
4.8 KiB
TypeScript

/**
* Vite configuration for Maestro Web Interface
*
* This config builds the web interface (both mobile and desktop)
* as a standalone bundle that can be served by the Fastify server.
*
* Output: dist/web/
*/
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
import { readFileSync } from 'fs';
// Read version from package.json
const packageJson = JSON.parse(
readFileSync(path.join(__dirname, 'package.json'), 'utf-8')
);
const appVersion = process.env.VITE_APP_VERSION || packageJson.version;
export default defineConfig(({ mode }) => ({
plugins: [react()],
// Entry point for web interface
root: path.join(__dirname, 'src/web'),
// Public directory for static assets (manifest.json, icons, etc.)
// Files here are copied to the build output root as-is
publicDir: path.join(__dirname, 'src/web/public'),
// Use relative paths for assets (served from Fastify)
base: './',
define: {
__APP_VERSION__: JSON.stringify(appVersion),
},
esbuild: {
// Strip console.log and console.debug in production builds
drop: mode === 'production' ? ['console', 'debugger'] : [],
},
resolve: {
alias: {
// Allow importing from renderer types/constants
'@renderer': path.join(__dirname, 'src/renderer'),
'@web': path.join(__dirname, 'src/web'),
'@shared': path.join(__dirname, 'src/shared'),
},
},
build: {
outDir: path.join(__dirname, 'dist/web'),
emptyOutDir: true,
// Generate source maps for debugging
sourcemap: true,
rollupOptions: {
input: {
// Single entry point that handles routing to mobile/desktop
main: path.join(__dirname, 'src/web/index.html'),
},
output: {
// Organize output by type
entryFileNames: 'assets/[name]-[hash].js',
// Use dynamic chunk names that preserve mobile/desktop distinction
chunkFileNames: (chunkInfo) => {
// Preserve mobile/desktop naming for their respective chunks
if (chunkInfo.name?.includes('mobile') || chunkInfo.facadeModuleId?.includes('/mobile/')) {
return 'assets/mobile-[hash].js';
}
if (chunkInfo.name?.includes('desktop') || chunkInfo.facadeModuleId?.includes('/desktop/')) {
return 'assets/desktop-[hash].js';
}
// Named chunks (react, vendor) keep their names
if (chunkInfo.name && !chunkInfo.name.startsWith('_')) {
return `assets/${chunkInfo.name}-[hash].js`;
}
return 'assets/[name]-[hash].js';
},
assetFileNames: 'assets/[name]-[hash].[ext]',
// Manual chunking for better caching and code splitting
manualChunks: (id) => {
// React core in its own chunk for optimal caching
if (id.includes('node_modules/react-dom')) {
return 'react';
}
if (id.includes('node_modules/react/') || id.includes('node_modules/react-is')) {
return 'react';
}
// Scheduler is a React dependency
if (id.includes('node_modules/scheduler')) {
return 'react';
}
// Mobile-specific dependencies (future-proofing for Phase 1)
// When mobile-specific libraries are added, they'll be bundled separately
if (id.includes('/mobile/') && !id.includes('node_modules')) {
return 'mobile';
}
// Desktop-specific dependencies (future-proofing for Phase 2)
// When desktop-specific libraries are added, they'll be bundled separately
if (id.includes('/desktop/') && !id.includes('node_modules')) {
return 'desktop';
}
// Shared web components stay in main bundle or get split automatically
// This allows React.lazy() to create async chunks for mobile/desktop
// Return undefined for other modules to let Rollup handle them
return undefined;
},
},
},
// Target modern browsers (web interface doesn't need legacy support)
target: 'es2020',
// Minimize bundle size
minify: 'esbuild',
// Report chunk sizes
reportCompressedSize: true,
},
// Development server (for testing web interface standalone)
server: {
port: 5174, // Different from renderer dev server (5173)
strictPort: true,
// Proxy API calls to the running Maestro app during development
proxy: {
'/api': {
target: 'http://localhost:45678',
changeOrigin: true,
},
'/ws': {
target: 'ws://localhost:45678',
ws: true,
},
},
},
// Preview server for testing production build
preview: {
port: 5175,
strictPort: true,
},
// Enable CSS code splitting
css: {
devSourcemap: true,
},
// Optimize dependencies
optimizeDeps: {
include: ['react', 'react-dom'],
},
}));