At a glance
- A long task is any main-thread task over 50 milliseconds; input waits while it runs.
- Total Blocking Time adds up the time beyond 50 ms in each long task after first paint; it is a lab proxy for INP.
- Code splitting with dynamic import() loads features when they are used.
- scheduler.yield() and setTimeout() break long work so the browser can respond in between.
Where the time goes
A script's transfer size is only part of its cost. After download, the browser parses, compiles and runs it on the main thread, the same thread that handles input, style, layout and paint. web.dev puts it plainly: "The browser blocks interactions from occurring while a task of any length is running." Tasks over 50 milliseconds are long tasks, and the time beyond 50 milliseconds is their blocking period.
In the lab, Total Blocking Time measures "the total amount of time after First Contentful Paint (FCP) where the main thread was blocked". web.dev calls it a reasonable lab proxy for INP but "not a substitute" for it. It carries 30% of the Lighthouse 10 performance score.
Typical sources on casino and sportsbook pages
- The lobby application bundle: catalog, filters, search, favorites, recently played and game launch code, often loaded together.
- Framework start-up: hydrating a large server-rendered lobby can be one long task.
- Live data: odds, jackpots and live table status updated through sockets, sometimes re-rendering large parts of the page on each message.
- Third-party scripts: covered in the third-party script audit.
Ship less at load: code splitting
web.dev's code splitting guide explains that dynamic import() "makes a request for a JavaScript resource at a later point during the page lifecycle", most often "at the point in which the user interacts with a given interactive element". Good candidates on a casino site:
| Feature | Load when |
|---|---|
| Advanced game filters | The filter panel is opened |
| Search index and suggestions | The search field receives focus |
| Cashier and payment flow | "Deposit" is tapped |
| Game launcher and provider SDK | A game is opened |
| Bet slip logic (sportsbook) | The first selection is added |
| Account and settings panels | The panel is opened |
Bundlers such as webpack, Parcel, Rollup and esbuild split code automatically where they meet dynamic import().
Break up long work
When work must happen, split it. web.dev describes setTimeout(), which defers work to the end of the task queue, and scheduler.yield(), an API "specifically designed for yielding to the main thread" whose continuation runs ahead of other similar tasks. It lists scheduler.yield() as supported in Chrome and Edge 129 and later and Firefox 142 and later, but not Safari, so use it with a setTimeout() fallback.
async function renderTiles(tiles) {
for (let i = 0; i < tiles.length; i++) {
drawTile(tiles[i]);
if (i % 24 === 23) {
await ('scheduler' in window && 'yield' in scheduler
? scheduler.yield()
: new Promise(r => setTimeout(r, 0)));
}
}
}
For live odds, batch updates and apply them once per frame instead of on every message, and update only the cells that changed.
Set a script budget
Agree a limit for JavaScript at load per template and check it in each release. The budgets guide covers how to choose numbers, and the calculator shows the share of JavaScript in your total.
Questions
Is a smaller bundle always faster?
Usually, but evaluation time also depends on what the code does when it runs. Profile both size and main-thread time.
Does defer fix long tasks?
It moves when a script runs, not how long it runs. A deferred script can still create long tasks, just later.
Should we use isInputPending()?
web.dev no longer recommends it. Use scheduler.yield() where supported, with setTimeout() as a fallback.
Sources
- web.dev, Optimize long tasks, last updated December 19, 2024.
- web.dev, Total Blocking Time (TBT), last updated October 15, 2025 (footer shows November 4, 2024).
- web.dev, Code-split JavaScript, last updated December 4, 2023.
- Chrome for Developers, How Lighthouse calculates your overall Performance score, footer date September 19, 2019 (lists Lighthouse 10 weights).
- web.dev, Optimize Interaction to Next Paint, last updated September 2, 2025.