"Reduce unused JavaScript" means your page downloads script that never runs during the visit. The browser still has to fetch, parse and compile all of it, which delays rendering on slow networks and keeps the main thread busy when users try to interact. On a typical site, a third or more of the JavaScript sent is unused JavaScript on any given page. This guide shows how to find it and cut it.
Why Unused JavaScript Hurts
Unused JavaScript costs you twice. First on the network: every extra kilobyte delays the download of resources that matter, which pushes back Largest Contentful Paint. Then on the CPU: parsing and compiling script blocks the main thread, which raises Total Blocking Time and makes interactions sluggish. On a mid-range phone, 1 MB of JavaScript can take more than a second of main-thread time before any of it is useful.
Common sources of unused JavaScript:
- One big bundle for every page. The checkout code ships on the blog, the admin dashboard ships on the homepage.
- Whole libraries for one function. Importing an entire date or utility library to format one date.
- Widgets that load up front but are only used after a click: modals, carousels, chat, video players, maps.
- Polyfills and legacy builds for browsers your users no longer run.
- Third-party scripts: tag managers, analytics, A/B testing and ad code, often with features you never enabled.
How to Find Unused JavaScript
- Coverage panel. In Chrome DevTools, open the command menu, run "Show Coverage", reload and use the page. Each script shows how many bytes were unused. Red bars in the source view are code that never executed.
- Bundle analyzer. Generate a treemap of your production bundles (for example
@next/bundle-analyzer,rollup-plugin-visualizerorsource-map-explorer) to see which dependencies take the most space. - Per-route view. Check the biggest routes separately. Unused JavaScript is usually concentrated in shared layout bundles that every page loads.
Remember that "unused" is per page and per visit. Code for a menu nobody opened counts as unused JavaScript even though it is needed sometimes. The fix for that kind is to load it later, not to delete it.
How to Reduce Unused JavaScript
1. Split bundles by route
Modern frameworks (Next.js, Remix, SvelteKit, Nuxt, Astro) split code per route automatically, as long as you do not defeat it. The usual mistake is importing a heavy module in a shared layout or a global provider, which drags it into every page. Move route-specific imports into the route itself.
2. Lazy-load what waits for a click
Anything that only appears after an interaction should load on demand with a dynamic import. The browser downloads it when it is needed, not on every page view.
3. Replace or trim heavy libraries
Check the treemap for large dependencies that do little. Import single functions instead of whole packages so tree shaking can drop the rest, and swap heavyweight libraries for smaller ones or built-in browser APIs (Intl.DateTimeFormat instead of a date library for formatting, fetch instead of an HTTP client).
4. Defer and audit third-party scripts
Third-party code is often the largest single source of unused JavaScript and the hardest to change. Remove tags nobody reads, load the rest after the page is interactive, and use your tag manager's triggers so scripts only load on the pages that need them. See third-party scripts and website performance for how to triage them.
5. Stop shipping legacy JavaScript
If your build still transpiles everything to ES5 and bundles polyfills for every browser, modern browsers download code they never run. Target the browsers your analytics show, and let the framework's modern build handle the rest.
6. Keep it from growing back
Unused JavaScript creeps back with every new dependency. Add a bundle size budget to CI (for example size-limit or your bundler's performance hints) so a pull request that adds 200 KB to the homepage fails before it ships.
What Not to Do
- Do not chase 0% unused. Some code is needed for interactions that only some visitors make; lazy-load it rather than removing it.
- Do not inline everything to avoid requests. Inlined JavaScript cannot be cached across pages, and it is still parsed.
- Do not move script to the end of the page and call it done. That fixes render-blocking resources, but the unused JavaScript still costs main-thread time.
How Scanverra Detects Unused JavaScript
A Scanverra performance audit lists the scripts that ship unused JavaScript with the bytes you could save for each, alongside related findings: legacy JavaScript, duplicated modules, unminified files, script boot-up time and third-party impact. It explains which metric each one affects (LCP, Total Blocking Time and, through them, interaction speed) and gives fixes written for the framework or CMS it detects. It measures a single page load in a lab, so it cannot tell you which code a logged-in user needs later in a session; use the Coverage panel on your key flows for that. For a quick overall read, start with the website speed test, then tackle LCP once your unused JavaScript is under control.