import { defineConfig, loadEnv } from 'vite' import react from '@vitejs/plugin-react' import fs from 'fs' import path from 'path' function injectFirebaseConfig(content: string, env: Record): string { return content .replace('__VITE_FIREBASE_API_KEY__', env.VITE_FIREBASE_API_KEY || '') .replace('__VITE_FIREBASE_AUTH_DOMAIN__', env.VITE_FIREBASE_AUTH_DOMAIN || '') .replace('__VITE_FIREBASE_PROJECT_ID__', env.VITE_FIREBASE_PROJECT_ID || '') .replace('__VITE_FIREBASE_MESSAGING_SENDER_ID__', env.VITE_FIREBASE_MESSAGING_SENDER_ID || '') .replace('__VITE_FIREBASE_APP_ID__', env.VITE_FIREBASE_APP_ID || '') } function swPlugin() { let env: Record = {} return { name: 'sw-plugin', config(_: unknown, { mode }: { mode: string }) { env = loadEnv(mode, process.cwd(), '') }, // Dev server: serve firebase-messaging-sw.js with injected config configureServer(server: { middlewares: { use: (path: string, handler: (req: unknown, res: { setHeader: (k: string, v: string) => void; end: (s: string) => void }, next: () => void) => void) => void } }) { server.middlewares.use('/firebase-messaging-sw.js', (_req, res) => { const swPath = path.resolve(__dirname, 'public/firebase-messaging-sw.js') if (fs.existsSync(swPath)) { const content = injectFirebaseConfig(fs.readFileSync(swPath, 'utf-8'), env) res.setHeader('Content-Type', 'application/javascript') res.end(content) } }) }, closeBundle() { // Cache-bust the main service worker const swPath = path.resolve(__dirname, 'dist/sw.js') if (fs.existsSync(swPath)) { const content = fs.readFileSync(swPath, 'utf-8') fs.writeFileSync(swPath, content.replace('__BUILD_TIME__', Date.now().toString())) } // Inject Firebase config into the FCM service worker const fswPath = path.resolve(__dirname, 'dist/firebase-messaging-sw.js') if (fs.existsSync(fswPath)) { const content = injectFirebaseConfig(fs.readFileSync(fswPath, 'utf-8'), env) fs.writeFileSync(fswPath, content) } }, } } // https://vite.dev/config/ export default defineConfig({ plugins: [react(), swPlugin()], server: { port: 8000, strictPort: false, }, optimizeDeps: { include: ['libsodium-wrappers'], }, build: { chunkSizeWarningLimit: 1000, rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules/firebase')) { return 'firebase' } if ( id.includes('node_modules/react/') || id.includes('node_modules/react-dom/') || id.includes('node_modules/react-router-dom/') ) { return 'react-vendor' } if (id.includes('node_modules/libsodium')) { return 'crypto' } if (id.includes('node_modules/driver.js')) { return 'driver' } }, }, }, }, })