From bbbe7b4036f0aa6d7de1a76c242d6718fbcdba52 Mon Sep 17 00:00:00 2001 From: 4gray Date: Sun, 3 May 2026 00:00:06 +0200 Subject: [PATCH] perf(renderer): inline splash + sync language hint + drop legacy polyfill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three first-paint fixes for cold app start. #1 — Inline splash in index.html Cold start used to show a blank Material-grey background until the ~1.5MB preloaded chunk + 300KB styles.css downloaded and Angular bootstrapped. On slow disks/networks that's 1-3+ s of "is the app frozen?" before any pixel of UI appears. Add a self-contained splash (inline CSS, no extra HTTP, no assets) — "IPTVnator" wordmark + a CSS spinner — that paints immediately from the parsed HTML. Removed in main.ts after bootstrapApplication() resolves, gated on requestAnimationFrame so the swap happens after AppComponent's first paint (no flash of empty background between splash removal and the real UI). Respects prefers-reduced-motion (spinner stops, opacity dims). #3 — Drop legacy `global = window` polyfill The inline + #initial-splash .splash-mark { + font-size: 18px; + font-weight: 600; + letter-spacing: 0.04em; + opacity: 0.85; + } + #initial-splash .splash-spinner { + width: 28px; + height: 28px; + border: 3px solid rgba(255, 255, 255, 0.12); + border-top-color: rgba(255, 255, 255, 0.7); + border-radius: 50%; + animation: initial-splash-spin 0.9s linear infinite; + } + @keyframes initial-splash-spin { + to { + transform: rotate(360deg); + } + } + @media (prefers-reduced-motion: reduce) { + #initial-splash .splash-spinner { + animation: none; + opacity: 0.6; + } + } + +
+ IPTVnator + +
diff --git a/apps/web/src/main.ts b/apps/web/src/main.ts index 9517f00e2..cf089c664 100644 --- a/apps/web/src/main.ts +++ b/apps/web/src/main.ts @@ -5,6 +5,16 @@ import { appConfig } from './app/app.config'; registerAppDateLocales(); -bootstrapApplication(AppComponent, appConfig).catch((err) => - console.error(err) -); +bootstrapApplication(AppComponent, appConfig) + .then(() => { + // Splash is rendered eagerly by index.html so the user sees something + // immediately instead of a blank Material-grey background. Once Angular + // is bootstrapped, AppComponent has rendered and we can drop the + // splash. requestAnimationFrame ensures the swap happens after the + // first AppComponent paint, avoiding a flash of empty background + // between splash removal and Angular's first frame. + requestAnimationFrame(() => { + document.getElementById('initial-splash')?.remove(); + }); + }) + .catch((err) => console.error(err));