// Бюджет размера web-бандла: node scripts/ci/web-budget.mjs [dist/assets] // Лимиты — gzip-байты; переопределяются env WEB_BUDGET_ENTRY_GZ / WEB_BUDGET_TOTAL_GZ. import { readdirSync, readFileSync } from 'node:fs' import { join } from 'node:path' import { fileURLToPath } from 'node:url' import { gzipSync } from 'node:zlib' export const DEFAULT_LIMITS = { entryGz: 25 * 1024, totalGz: 560 * 1024, } export function measure(dir) { let total = 0 let entry = 0 for (const name of readdirSync(dir)) { if (!name.endsWith('.js')) continue const gz = gzipSync(readFileSync(join(dir, name))).length total += gz if (/^index-.*\.js$/.test(name)) entry = Math.max(entry, gz) } return { entryGz: entry, totalGz: total } } export function checkBudget(dir, limits = DEFAULT_LIMITS) { const sizes = measure(dir) const errors = [] if (sizes.entryGz === 0) errors.push('entry chunk index-*.js не найден') if (sizes.entryGz > limits.entryGz) errors.push(`entry gzip ${sizes.entryGz} > ${limits.entryGz}`) if (sizes.totalGz > limits.totalGz) errors.push(`total gzip ${sizes.totalGz} > ${limits.totalGz}`) return { sizes, errors } } if (process.argv[1] === fileURLToPath(import.meta.url)) { const dir = process.argv[2] ?? 'apps/web/dist/assets' const limits = { entryGz: Number(process.env.WEB_BUDGET_ENTRY_GZ ?? DEFAULT_LIMITS.entryGz), totalGz: Number(process.env.WEB_BUDGET_TOTAL_GZ ?? DEFAULT_LIMITS.totalGz), } const { sizes, errors } = checkBudget(dir, limits) console.log('web bundle (gzip):', sizes, 'limits:', limits) if (errors.length) { console.error('BUDGET EXCEEDED:\n - ' + errors.join('\n - ')) process.exit(1) } }