Reduce Unused JavaScript
"Reduce unused JavaScript" is one of the most common Lighthouse warnings, and one of the most misunderstood: it doesn't mean dead code sitting in a file somewhere. It means code the browser downloaded, parsed and compiled for this specific page load, but never actually executed.
What it means
Lighthouse runs coverage analysis against every script on the page and reports the percentage of bytes that were never used during that load. A large marketing-site bundle that includes an admin dashboard, a checkout flow the visitor never triggers, or a full component library when the page only renders three components will all show up here, often with tens or hundreds of kilobytes flagged.
Why it matters
Unused JavaScript still costs full price on the way in: it has to be downloaded over the network, parsed, and (for module-level code) compiled, all on the main thread. That work competes directly with the browser's ability to respond to input, which shows up as a worse Total Blocking Time (TBT) and a worse Interaction to Next Paint (INP), the Core Web Vital that replaced First Input Delay. On a slow mobile CPU, parsing and compiling a large bundle can take longer than the network transfer itself.
How to fix it
- Code-split by route. Instead of one bundle for the whole app, ship only the JavaScript the current page needs:
// instead of a static top-level import
import Checkout from './Checkout';
// load it only when it's actually needed
const Checkout = await import('./Checkout');
- Let your bundler tree-shake. Tree-shaking removes exports that are never imported anywhere, but only works reliably with ES module syntax (
import/export), notrequire(). Check your bundler's production build output for an "unused exports" or "tree-shaking" report to confirm it's actually happening. - Remove libraries and polyfills you no longer need. A common case is a polyfill bundle (e.g. for
Promiseorfetch) still being shipped to every browser years after the last browser that needed it lost meaningful market share. - Defer third-party scripts (analytics, chat widgets, A/B testing tools) so they load after the main content is interactive, rather than competing with your own code for parse time on page load. The same
deferattribute and the other techniques for eliminating render-blocking resources apply here too.
How to verify
Re-test the page and compare the "Est Savings" figure on this audit before and after. For a more precise picture during development, open your browser's DevTools Coverage panel (Chrome: Cmd/Ctrl+Shift+P → "Show Coverage") and reload the page to see exactly which lines of each script were used.
Test your site
Run a free scan to see whether this audit applies to your pages, on mobile and desktop, with lab and field data side by side.
Run a free test