Why the OnTiv homepage now loads less code
· 3 min read
When you open ontiv.app for the first time, you are usually looking at the landing page, not the player. Yet the page was downloading code that only the player needs. We ran Google's PageSpeed Insights on the live site, looked at what it flagged, and fixed the parts that were genuinely ours. Here is what we found and what we did.
What PageSpeed pointed at
Two things stood out on mobile:
- Unused JavaScript. Estimated savings of 157 KiB. About 86 KiB of that was our own bundle and about 71 KiB was Google's analytics script.
- A layout shift. The page moved around when the app finished loading.
Moving code out of the first load
The playlist parser, the Xtream Codes and Stalker Portal clients, the program-guide loader, and the player's playback hook all sat in the initial bundle even though nobody needs them until they load a playlist. They now load on demand, when you actually add a playlist.
We also found a validation library, zod, being pulled into every first visit by a type definition we never used at runtime. Replacing it with a plain type removed the library from the first load altogether.
The result, measured on our build: the initial JavaScript went from about 542 KiB to about 432 KiB uncompressed, roughly 20 percent less. On PageSpeed's mobile run, the main bundle transferred went from 153 KiB to 124 KiB.
Fixing the layout shift at the source
The homepage ships with static HTML so it can paint before the app starts. That copy had been written by hand, and it had drifted from what the app really renders: it showed four feature cards where the app shows seven, and was missing whole sections. When the app started, it replaced the static page with a different one, and everything below the top moved.
We stopped maintaining two copies. The landing page is now a single component. At build time we render it to HTML for the static version, so the static page and the live page are the same thing by construction. On a production build, we measured no layout shift from that swap.
One trade-off: analytics now waits
Google's analytics script is large, and it was loading right when the page was trying to paint. It now loads after the page is up: on your first interaction, or a couple of seconds after the page finishes loading, whichever comes first. Events that happen in the meantime are queued and sent when it arrives, so nothing is lost.
The cost is that a visit shorter than a few seconds, with no click, scroll or keypress, is no longer counted. We think that is a fair price for a faster first paint, and we would rather say so than hide it.
What we did not fix
Honesty matters more than a tidy story. PageSpeed's overall score barely moved, because much of what remains is the React runtime itself, plus web fonts that load after the first paint. Those are the next things we want to look at.
If you are curious about how any of this works, or you spot something slow, get in touch.