UNPKG

codebase-asset-optimizer

Version:

Professional CLI development tool for optimizing and managing assets in codebases. Detects unused assets, optimizes images to WebP, optimizes videos, and automatically replaces asset references. GIFs are preserved unchanged to maintain animation functiona

170 lines • 7.78 kB
#!/usr/bin/env node /** * Performance Benchmark for codebase-asset-optimizer * Shows users the real-world impact of asset optimization */ import fs from 'fs-extra'; import path from 'path'; import chalk from 'chalk'; import { execSync } from 'child_process'; const TEST_PROJECT_DIR = path.join(process.cwd(), 'test-project'); const PUBLIC_DIR = path.join(TEST_PROJECT_DIR, 'public'); async function getDirectorySize(dirPath) { let totalSize = 0; async function calculateSize(currentPath) { const stats = await fs.stat(currentPath); if (stats.isDirectory()) { const files = await fs.readdir(currentPath); for (const file of files) { await calculateSize(path.join(currentPath, file)); } } else { totalSize += stats.size; } } if (await fs.pathExists(dirPath)) { await calculateSize(dirPath); } return totalSize; } function formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } async function countAssets(dirPath) { let images = 0; let videos = 0; if (await fs.pathExists(dirPath)) { const items = await fs.readdir(dirPath, { withFileTypes: true }); for (const item of items) { if (item.isDirectory()) { const subCounts = await countAssets(path.join(dirPath, item.name)); images += subCounts.images; videos += subCounts.videos; } else { const ext = path.extname(item.name).toLowerCase(); if (['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg'].includes(ext)) { images++; } else if (['.mp4', '.webm', '.mov', '.avi', '.mkv'].includes(ext)) { videos++; } } } } return { images, videos }; } async function runBenchmark() { console.log(chalk.cyan('\n⚔ Asset Optimization Performance Benchmark')); console.log(chalk.cyan('=============================================\n')); // Check if test project exists - handle different execution contexts let testProjectDir = TEST_PROJECT_DIR; // If running from test-project directory, use current directory if (process.cwd().endsWith('test-project')) { testProjectDir = process.cwd(); } // If running from project root, use test-project subdirectory else if (await fs.pathExists(TEST_PROJECT_DIR)) { testProjectDir = TEST_PROJECT_DIR; } // If neither exists, exit gracefully else { console.log(chalk.red('āŒ Test project not found. Expected to find test assets.')); console.log(chalk.gray(' Run this from the project root or test-project directory.')); return; } const publicDir = path.join(testProjectDir, 'public'); if (!await fs.pathExists(publicDir)) { console.log(chalk.red('āŒ Public directory not found in test project.')); return; } console.log(chalk.blue('šŸ“Š Analyzing current state...')); // Get baseline metrics const beforeSize = await getDirectorySize(publicDir); const assetCounts = await countAssets(publicDir); console.log(chalk.white('šŸ“ Current Asset Inventory:')); console.log(chalk.gray(` Images: ${assetCounts.images}`)); console.log(chalk.gray(` Videos: ${assetCounts.videos}`)); console.log(chalk.gray(` Total size: ${formatBytes(beforeSize)}`)); // Run audit to get optimization potential console.log(chalk.blue('\nšŸ” Analyzing optimization potential...')); try { const auditOutput = execSync('npm run audit:assets test-project', { encoding: 'utf8', stdio: 'pipe' }); // Extract optimization info from audit output const optimizableMatch = auditOutput.match(/Optimizable: (\d+) \(([^)]+)\)/); if (optimizableMatch) { const optimizableCount = optimizableMatch[1]; const optimizableSize = optimizableMatch[2]; console.log(chalk.green(`āœ… Found ${optimizableCount} assets that can be optimized`)); console.log(chalk.gray(` Current size: ${optimizableSize}`)); } } catch (error) { console.log(chalk.yellow('āš ļø Could not run audit, but continuing...')); } // Run dry-run to show what would happen console.log(chalk.blue('\nšŸ”® Simulating optimization (dry-run)...')); try { const dryRunOutput = execSync('npm run optimize:assets:dry test-project', { encoding: 'utf8', stdio: 'pipe' }); // Extract potential savings const savingsMatch = dryRunOutput.match(/Estimated savings: (\d+)-(\d+)%/); if (savingsMatch) { const minSavings = parseInt(savingsMatch[1]); const maxSavings = parseInt(savingsMatch[2]); const estimatedMinSize = beforeSize * (1 - maxSavings / 100); const estimatedMaxSize = beforeSize * (1 - minSavings / 100); console.log(chalk.green('šŸ“ˆ Optimization Impact Projection:')); console.log(chalk.white(` Current total: ${formatBytes(beforeSize)}`)); console.log(chalk.green(` Estimated after: ${formatBytes(estimatedMinSize)} - ${formatBytes(estimatedMaxSize)}`)); console.log(chalk.green(` Potential savings: ${formatBytes(beforeSize - estimatedMaxSize)} - ${formatBytes(beforeSize - estimatedMinSize)}`)); console.log(chalk.green(` Reduction: ${minSavings}% - ${maxSavings}%`)); } } catch (error) { console.log(chalk.yellow('āš ļø Could not run dry-run simulation')); } // Show performance benefits console.log(chalk.blue('\nšŸš€ Performance Benefits:')); console.log(chalk.white(' šŸ“± Mobile Performance:')); console.log(chalk.green(' • Faster page loads on slow connections')); console.log(chalk.green(' • Reduced data usage for users')); console.log(chalk.green(' • Better Core Web Vitals scores')); console.log(chalk.white('\n 🌐 Web Performance:')); console.log(chalk.green(' • Improved LCP (Largest Contentful Paint)')); console.log(chalk.green(' • Better SEO rankings')); console.log(chalk.green(' • Reduced CDN/hosting costs')); console.log(chalk.white('\n šŸ’¾ Storage Benefits:')); console.log(chalk.green(' • Smaller repository size')); console.log(chalk.green(' • Faster CI/CD deployments')); console.log(chalk.green(' • Lower bandwidth costs')); // Show commands to take action console.log(chalk.blue('\nšŸŽÆ Take Action:')); console.log(chalk.cyan(' 1. Review what would be optimized:')); console.log(chalk.white(' npm run optimize:assets:dry test-project')); console.log(chalk.cyan('\n 2. Apply optimizations safely:')); console.log(chalk.white(' npm run optimize:assets test-project')); console.log(chalk.cyan('\n 3. Use for your real project:')); console.log(chalk.white(' npm run audit:assets')); console.log(chalk.white(' npm run optimize:assets:dry')); console.log(chalk.white(' npm run optimize:assets')); console.log(chalk.green('\n✨ Start optimizing and boost your app performance!')); } // Run the benchmark runBenchmark().catch((error) => { console.error(chalk.red('\nāŒ Benchmark failed!')); console.error(chalk.red(`Error: ${error.message}`)); process.exit(1); }); //# sourceMappingURL=benchmark.js.map