/** * LuckyChit Web Server * Express server to serve Flutter web build with proper caching * * Usage: * node web-server.js * Or with PM2: * pm2 start web-server.js --name "luckychit-web" */ const express = require('express'); const path = require('path'); const fs = require('fs'); const app = express(); const PORT = process.env.PORT || 8080; const BUILD_DIR = path.join(__dirname, 'build/web'); // Check if build directory exists if (!fs.existsSync(BUILD_DIR)) { console.error('❌ Error: build/web directory not found!'); console.error(' Please run: flutter build web --release'); process.exit(1); } // Security headers app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'SAMEORIGIN'); res.setHeader('X-XSS-Protection', '1; mode=block'); next(); }); // Serve static files with caching strategy app.use(express.static(BUILD_DIR, { maxAge: '1y', // Cache static assets for 1 year immutable: true, setHeaders: (res, filePath) => { // Don't cache HTML files (always serve fresh) if (filePath.endsWith('.html')) { res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); } } })); // Handle Flutter routes (SPA - Single Page Application) // Any route not found as a static file should serve index.html app.get('*', (req, res) => { res.sendFile(path.join(BUILD_DIR, 'index.html')); }); // Error handling app.use((err, req, res, next) => { console.error('Error:', err); res.status(500).send('Internal Server Error'); }); // Start server app.listen(PORT, '0.0.0.0', () => { console.log(''); console.log('✅ LuckyChit Flutter Web App'); console.log('============================'); console.log(`🌐 Running on: http://localhost:${PORT}`); console.log(`📁 Serving: ${BUILD_DIR}`); console.log(''); console.log('📝 Logs:'); console.log(' Access: http://localhost:' + PORT); console.log(''); }); // Graceful shutdown process.on('SIGTERM', () => { console.log('SIGTERM received, shutting down gracefully...'); process.exit(0); }); process.on('SIGINT', () => { console.log('SIGINT received, shutting down gracefully...'); process.exit(0); });