/** * Bundle-size gate for CI. * * Finds all .js files in dist/remote/static/js/, measures their gzip size, * reports per-file and total, and fails if total exceeds the budget. * * Budgets: * - Total remote bundle: <= 2000 kB gzip */ import { readFileSync, readdirSync, statSync } from "node:fs"; import { join } from "node:path"; import { gzipSync } from "node:zlib"; const BUDGET_TOTAL_KB = 2000; const JS_DIR = "dist/remote/static/js"; function collectJsFiles(dir) { const results = []; let entries; try { entries = readdirSync(dir); } catch { return results; } for (const entry of entries) { const full = join(dir, entry); const stat = statSync(full, { throwIfNoEntry: false }); if (!stat) continue; if (stat.isDirectory()) { results.push(...collectJsFiles(full)); } else if (entry.endsWith(".js")) { results.push(full); } } return results; } const files = collectJsFiles(JS_DIR); if (files.length === 0) { console.error(`No .js files found in ${JS_DIR}. Did the build run?`); process.exit(1); } let totalGzip = 0; const rows = []; for (const file of files) { const raw = readFileSync(file); const gzipped = gzipSync(raw); const gzipKB = gzipped.length / 1024; totalGzip += gzipKB; rows.push({ file: file.replace("dist/remote/", ""), rawKB: (raw.length / 1024).toFixed(1), gzipKB: gzipKB.toFixed(1) }); } rows.sort((a, b) => parseFloat(b.gzipKB) - parseFloat(a.gzipKB)); console.log("\n--- Bundle Size Report ---\n"); console.log( "File".padEnd(60) + "Raw (kB)".padStart(12) + "Gzip (kB)".padStart(12) ); console.log("-".repeat(84)); for (const r of rows) { console.log( r.file.padEnd(60) + r.rawKB.padStart(12) + r.gzipKB.padStart(12) ); } console.log("-".repeat(84)); console.log( "TOTAL".padEnd(60) + "".padStart(12) + totalGzip.toFixed(1).padStart(12) ); console.log(`\nBudget: ${BUDGET_TOTAL_KB} kB gzip`); if (totalGzip > BUDGET_TOTAL_KB) { console.error(`\nFAILED: Total gzip size ${totalGzip.toFixed(1)} kB exceeds budget of ${BUDGET_TOTAL_KB} kB`); process.exit(1); } else { console.log(`\nPASSED: ${totalGzip.toFixed(1)} kB / ${BUDGET_TOTAL_KB} kB budget`); }