/** * Optimized Build Script * ---------------------- * This script runs a sequence of optimizations before building the Next.js app: * 1. Optimizes images (resize, compress, convert to modern formats) * 2. Analyzes and reduces unused JavaScript * 3. Optimizes CSS * 4. Runs the production build */ const { execSync } = require('child_process'); const path = require('path'); const fs = require('fs'); // Check if running in CI environment (like Vercel) const isCI = process.env.CI === 'true' || process.env.VERCEL === '1'; console.log('šŸš€ Starting optimized build process...'); console.log(isCI ? 'Running in CI environment (Vercel)' : 'Running in local environment'); // Create directory for build reports const REPORTS_DIR = path.join(__dirname, '../build-reports'); if (!fs.existsSync(REPORTS_DIR)) { fs.mkdirSync(REPORTS_DIR, { recursive: true }); } // Utility to run commands and handle errors function runCommand(command, name) { console.log(`\nšŸ”„ Running ${name}...`); try { execSync(command, { stdio: 'inherit' }); console.log(`āœ… ${name} completed successfully`); return true; } catch (error) { console.error(`āŒ ${name} failed:`, error.message); return false; } } // Conditional execution based on environment if (!isCI) { // 1. Install required dependencies if they don't exist console.log('\nšŸ“¦ Checking build dependencies...'); try { // Check if sharp and glob are installed require.resolve('sharp'); require.resolve('glob'); console.log('āœ… All dependencies installed'); } catch (error) { console.log('šŸ”„ Installing missing dependencies...'); runCommand('npm install --save-dev sharp glob', 'Install dependencies'); } // 2. Run Image Optimization - Skip in CI environment runCommand('node scripts/optimize-images.js', 'Image Optimization'); // 3. Analyze bundle size - Skip in CI environment const shouldAnalyze = process.env.ANALYZE === 'true'; if (shouldAnalyze) { console.log('\nšŸ“Š Analyzing initial bundle size...'); runCommand( 'ANALYZE=true next build', 'Bundle analysis' ); } } // 4. Run Next.js production build with all optimizations console.log('\nšŸ—ļø Building optimized production bundle...'); runCommand( 'next build', 'Production build' ); // 5. Verify build output const BUILD_OUTPUT_DIR = path.join(__dirname, '../.next'); if (fs.existsSync(BUILD_OUTPUT_DIR)) { console.log(`\nāœ… Build completed successfully in ${BUILD_OUTPUT_DIR}`); if (!isCI) { // Get build stats - Skip in CI environment const buildSize = getFolderSize(BUILD_OUTPUT_DIR); console.log(`šŸ“Š Build size: ${(buildSize / 1024 / 1024).toFixed(2)} MB`); console.log('\nšŸ” Next steps:'); console.log('1. Run "npm run start" to test the optimized build'); console.log('2. Check for any performance issues'); console.log('3. Deploy to production'); } } else { console.error('āŒ Build output not found. Build may have failed.'); process.exit(1); } // Helper function to calculate folder size function getFolderSize(folderPath) { let totalSize = 0; function readDir(dirPath) { const items = fs.readdirSync(dirPath); for (const item of items) { const itemPath = path.join(dirPath, item); const stats = fs.statSync(itemPath); if (stats.isFile()) { totalSize += stats.size; } else if (stats.isDirectory()) { readDir(itemPath); } } } readDir(folderPath); return totalSize; }