diff --git a/code/websites/pokedex.online/scripts/verify-build.js b/code/websites/pokedex.online/scripts/verify-build.js new file mode 100644 index 0000000..ec23735 --- /dev/null +++ b/code/websites/pokedex.online/scripts/verify-build.js @@ -0,0 +1,159 @@ +/** + * Build Verification Script + * + * Verifies that the production build was successful and contains + * all necessary files for deployment. + */ + +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const DIST_DIR = path.join(__dirname, '..', 'dist'); +const REQUIRED_FILES = [ + 'index.html', + 'assets' // Directory +]; + +const errors = []; +const warnings = []; + +console.log('šŸ” Verifying build output...\n'); + +// Check if dist directory exists +if (!fs.existsSync(DIST_DIR)) { + errors.push('dist/ directory not found - build may have failed'); + console.error('āŒ dist/ directory not found'); + process.exit(1); +} + +console.log(`šŸ“ Build directory: ${DIST_DIR}`); + +// Check required files +console.log('\nšŸ“‹ Checking required files:'); +for (const file of REQUIRED_FILES) { + const filePath = path.join(DIST_DIR, file); + const exists = fs.existsSync(filePath); + + if (exists) { + const stats = fs.statSync(filePath); + const isDir = stats.isDirectory(); + console.log(` āœ… ${file} ${isDir ? '(directory)' : `(${(stats.size / 1024).toFixed(2)} KB)`}`); + } else { + errors.push(`Required file missing: ${file}`); + console.log(` āŒ ${file} - MISSING`); + } +} + +// Check for JavaScript bundles +console.log('\nšŸ“¦ Checking JavaScript bundles:'); +const assetsDir = path.join(DIST_DIR, 'assets'); +if (fs.existsSync(assetsDir)) { + const files = fs.readdirSync(assetsDir); + const jsFiles = files.filter(f => f.endsWith('.js')); + const cssFiles = files.filter(f => f.endsWith('.css')); + + if (jsFiles.length === 0) { + errors.push('No JavaScript bundles found in assets/'); + console.log(' āŒ No JavaScript bundles found'); + } else { + console.log(` āœ… Found ${jsFiles.length} JavaScript bundles`); + + // Show bundle sizes + const totalJsSize = jsFiles.reduce((total, file) => { + const stats = fs.statSync(path.join(assetsDir, file)); + return total + stats.size; + }, 0); + console.log(` Total JS size: ${(totalJsSize / 1024 / 1024).toFixed(2)} MB`); + + // Warn if bundles are too large + jsFiles.forEach(file => { + const stats = fs.statSync(path.join(assetsDir, file)); + const sizeMB = stats.size / 1024 / 1024; + if (sizeMB > 1) { + warnings.push(`Large bundle detected: ${file} (${sizeMB.toFixed(2)} MB)`); + } + }); + } + + if (cssFiles.length === 0) { + warnings.push('No CSS files found in assets/'); + console.log(' āš ļø No CSS files found'); + } else { + console.log(` āœ… Found ${cssFiles.length} CSS files`); + } +} else { + errors.push('assets/ directory not found'); + console.log(' āŒ assets/ directory not found'); +} + +// Check index.html +console.log('\nšŸ“„ Checking index.html:'); +const indexPath = path.join(DIST_DIR, 'index.html'); +if (fs.existsSync(indexPath)) { + const content = fs.readFileSync(indexPath, 'utf8'); + + // Check for script tags + const scriptTags = content.match(/]*src="[^"]*"[^>]*>/g); + if (scriptTags && scriptTags.length > 0) { + console.log(` āœ… Found ${scriptTags.length} script tag(s)`); + } else { + errors.push('No script tags found in index.html'); + console.log(' āŒ No script tags found'); + } + + // Check for stylesheet links + const linkTags = content.match(/]*rel="stylesheet"[^>]*>/g); + if (linkTags && linkTags.length > 0) { + console.log(` āœ… Found ${linkTags.length} stylesheet link(s)`); + } else { + warnings.push('No stylesheet links found in index.html'); + console.log(' āš ļø No stylesheet links found'); + } +} else { + errors.push('index.html not found'); + console.log(' āŒ index.html not found'); +} + +// Calculate total build size +console.log('\nšŸ“Š Build Statistics:'); +function getDirSize(dirPath) { + let size = 0; + const files = fs.readdirSync(dirPath); + + for (const file of files) { + const filePath = path.join(dirPath, file); + const stats = fs.statSync(filePath); + + if (stats.isDirectory()) { + size += getDirSize(filePath); + } else { + size += stats.size; + } + } + + return size; +} + +const totalSize = getDirSize(DIST_DIR); +console.log(` Total build size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`); + +// Summary +console.log('\n' + '='.repeat(50)); +if (errors.length > 0) { + console.log('\nāŒ Build verification FAILED\n'); + errors.forEach(error => console.error(` - ${error}`)); + process.exit(1); +} + +if (warnings.length > 0) { + console.log('\nāš ļø Build verification passed with warnings:\n'); + warnings.forEach(warning => console.warn(` - ${warning}`)); +} + +console.log('\nāœ… Build verification PASSED'); +console.log(' All required files present and valid'); +console.log(' Ready for deployment\n');