Lazy-load seasonal theme CSS/keyframes only when a seasonal overlay is active #167

Closed
opened 2026-09-17 23:06:35 -04:00 by jared · 1 comment
Owner

Verify with the bundle analyser whether the 11 seasonal overlays (and their particle keyframes) are in the main CSS/JS for everyone year-round. If so, split each overlay into its own chunk (dynamic import() when seasonalThemeOverride/auto-date selects it), keep the auto-date decision logic in the main bundle. Same for the animated chat backgrounds if they are always bundled. Report the before/after in check-bundle-size output.

Verify with the bundle analyser whether the 11 seasonal overlays (and their particle keyframes) are in the main CSS/JS for everyone year-round. If so, split each overlay into its own chunk (dynamic `import()` when `seasonalThemeOverride`/auto-date selects it), keep the auto-date decision logic in the main bundle. Same for the animated chat backgrounds if they are always bundled. Report the before/after in `check-bundle-size` output.
jared added this to the Features 2026-Q4 milestone 2026-09-17 23:06:35 -04:00
jared added the priority: mediumperformancearea: appearance labels 2026-09-17 23:06:35 -04:00
jared self-assigned this 2026-09-17 23:06:35 -04:00
Author
Owner

Verified and done for the overlays in 8658ec05: all 11 seasonal overlays (particles + their vanilla-extract keyframes) were in the main JS and the main CSS year-round. Each is now a React.lazy chunk (Halloween-*.js + Halloween-*.css, …) fetched only when that season is active (auto date or override) or previewed in Settings → Appearance; the schedule/override decision stays in the main bundle.

check-bundle-size before → after: largest chunk 332.4 → 320.1 kB gzip, main CSS 68.4 → 56.5 kB, total gzip 1551.6 → 1561.3 kB (per-chunk overhead, paid only when a season is on). Headless check: zero theme chunks requested at startup with auto out of season; opening the Settings grid fetches the 11 previews; picking Halloween renders the full-screen overlay.

Animated chat backgrounds: the 18 background definitions are ~117 KB of source (inline data-URI SVG strings) behind a synchronous getChatBg() used by RoomView, the call embed, the sidebar and the settings previews — splitting them needs an async hook at every call site for maybe 20–30 kB gzip. Leaving that as a possible follow-up rather than doing it here.

Verified and done for the overlays in `8658ec05`: all 11 seasonal overlays (particles + their vanilla-extract keyframes) were in the main JS *and* the main CSS year-round. Each is now a `React.lazy` chunk (`Halloween-*.js` + `Halloween-*.css`, …) fetched only when that season is active (auto date or override) or previewed in Settings → Appearance; the schedule/override decision stays in the main bundle. `check-bundle-size` before → after: largest chunk **332.4 → 320.1 kB** gzip, main CSS **68.4 → 56.5 kB**, total gzip 1551.6 → 1561.3 kB (per-chunk overhead, paid only when a season is on). Headless check: zero theme chunks requested at startup with `auto` out of season; opening the Settings grid fetches the 11 previews; picking Halloween renders the full-screen overlay. Animated chat backgrounds: the 18 background definitions are ~117 KB of *source* (inline data-URI SVG strings) behind a synchronous `getChatBg()` used by RoomView, the call embed, the sidebar and the settings previews — splitting them needs an async hook at every call site for maybe 20–30 kB gzip. Leaving that as a possible follow-up rather than doing it here.
jared closed this issue 2026-09-19 13:01:24 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/cinny#167