// Bundle-size budget gate. Measures the gzipped JS each built HTML entry actually loads and // fails CI if any part overruns its budget — a guard against an accidental heavy dependency. // The build has two entries (vite rollupOptions.input): the game app (index.html, served at // /app/ + /telegram/) and the landing (landing.html, served at /). Rollup hoists the code // shared by both (the Svelte runtime + i18n + aboutContent) into one chunk each entry // preloads, so a page's real payload is its own entry chunk plus that shared chunk. // // Three independent gates on the natural chunk boundaries, each with realistic headroom: // - app entry (main): the app's own code; grows with features. // - shared (svelte+i18n): near-static framework runtime; only drifts on a dep/Svelte bump. // - landing own: the landing's own code; kept minimal. // Today ~74 KB (app entry) + ~23 KB (shared) = ~97 KB for the app; the landing's own chunk is // ~2 KB. Lazy-loading was analysed and rejected for R5 (no total-size win — every chunk still // ships and is summed — plus added request latency); the bulk is the Connect/FlatBuffers // transport runtime + generated bindings + the Svelte runtime, irreducible within scope. See // PRERELEASE.md R5 for the full rationale. import { readFileSync, existsSync } from 'node:fs'; import { gzipSync } from 'node:zlib'; import { join } from 'node:path'; const DIST = 'dist'; // Per-chunk gzip budgets in KB. const BUDGET = { app: 100, shared: 30, landing: 5 }; // gzipped returns the gzipped byte size of a built asset, or 0 when the reference is not a // local file (e.g. the Telegram SDK loaded from a CDN) or is missing. function gzipped(file) { return file && existsSync(file) ? gzipSync(readFileSync(file)).length : 0; } // attr reads a double-quoted HTML attribute from a single tag string. function attr(tag, name) { const m = tag.match(new RegExp(`\\s${name}="([^"]+)"`)); return m ? m[1] : null; } // localAsset maps an HTML asset URL to its path under dist/, or null for an external URL. function localAsset(url) { return !url || /^https?:/.test(url) ? null : join(DIST, url.replace(/^\.?\/+/, '')); } // entryAssets parses a built HTML entry and returns the local JS it eagerly loads: the module // entry chunk (