166 lines
4.7 KiB
JavaScript
166 lines
4.7 KiB
JavaScript
/**
|
||
* 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(/<script[^>]*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(/<link[^>]*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');
|