import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { fileURLToPath, URL } from 'node:url' // Plugin to replace BUILD_TIMESTAMP in index.html at build function htmlTimestampPlugin() { return { name: 'html-timestamp', transformIndexHtml(html) { return html.replace('BUILD_TIMESTAMP', new Date().toISOString()) } } } export default defineConfig({ plugins: [vue(), htmlTimestampPlugin()], // Base path for IIS sub-application at /roa2web base: process.env.NODE_ENV === 'production' ? '/roa2web/' : '/', resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), '@shared': fileURLToPath(new URL('./src/shared', import.meta.url)), '@reports': fileURLToPath(new URL('./src/modules/reports', import.meta.url)), '@data-entry': fileURLToPath(new URL('./src/modules/data-entry', import.meta.url)) }, dedupe: ['vue', 'vue-router', 'pinia', 'primevue'] }, server: { port: 3000, host: true, // Allow Tailscale VPN access for mobile debugging allowedHosts: ['.ts.net', 'claude-agent'], // Disable file watching to prevent WSL2 deadlock watch: null, // Disable HMR completely hmr: false, // Single proxy configuration for unified backend proxy: { '/api': { target: 'http://localhost:8000', changeOrigin: true, secure: false, configure: (proxy, options) => { proxy.on('proxyReq', (proxyReq, req, res) => { // Preserve authorization header during redirects if (req.headers.authorization) { proxyReq.setHeader('Authorization', req.headers.authorization); } // Preserve X-Selected-Company header for data-entry if (req.headers['x-selected-company']) { proxyReq.setHeader('X-Selected-Company', req.headers['x-selected-company']); } }); } }, '/uploads': { target: 'http://localhost:8000', changeOrigin: true, secure: false } } }, optimizeDeps: { include: ['vue', 'vue-router', 'pinia'] }, build: { outDir: 'dist', sourcemap: true, commonjsOptions: { include: [/node_modules/] }, // Cache busting - generate new hashes on each build assetsInlineLimit: 0, // Don't inline small assets, use separate files with hash rollupOptions: { output: { // Force unique hashes for all files entryFileNames: `assets/[name].[hash].js`, chunkFileNames: `assets/[name].[hash].js`, assetFileNames: `assets/[name].[hash].[ext]`, // Manual chunks for better lazy loading and code splitting manualChunks: { // Core vendors 'vendor-core': ['vue', 'vue-router', 'pinia'], 'vendor-primevue': [ 'primevue/config', 'primevue/button', 'primevue/datatable', 'primevue/column', 'primevue/inputtext', 'primevue/password', 'primevue/dropdown', 'primevue/calendar', 'primevue/dialog', 'primevue/toast', 'primevue/confirmdialog' ], 'vendor-utils': ['axios', 'date-fns'], // Charts (reports only - will be lazy loaded) 'vendor-charts': ['chart.js', 'vue-chartjs'], // Excel/PDF exports (lazy loaded) 'vendor-export': ['xlsx', 'jspdf', 'jspdf-autotable'] // Note: Reports and Data Entry modules will be lazy loaded via dynamic imports } } } }, // Add timestamp to build for versioning define: { __APP_VERSION__: JSON.stringify(new Date().toISOString()), __BUILD_TIMESTAMP__: JSON.stringify(Date.now()) } })