How to Fix Unused JavaScript
Lighthouse flags JavaScript that is downloaded but never executed during page load. Learn how to identify dead code and reduce your JavaScript bundle size.
What Lighthouse Is Telling You
When Lighthouse flags unused JavaScript, it means your page is downloading JavaScript that never executes during load. This wastes bandwidth and increases Total Blocking Time because the browser must parse all downloaded JavaScript, even the parts it never runs.
Lighthouse shows each script file with the total bytes transferred and the bytes that went unused. A 400 KB bundle where 280 KB is unused means the user downloads 70% more JavaScript than the page needs.
Why There Is Unused JavaScript
- No code splitting — The entire application ships in one bundle, including code for pages the user has not visited
- Unused library features — Importing all of lodash when you use three functions. Importing all of Material UI when you use two components
- Legacy polyfills — Babel polyfills for
Promise,Array.from, orObject.assignshipped to browsers that already support them natively - Dead code — Features that were removed from the UI but whose code still ships in the bundle
- Third-party bloat — Analytics SDKs, chat widgets, or A/B testing libraries loading their full code upfront
The Old Way to Fix It
- Run Lighthouse and find the unused JavaScript audit
- Open Chrome DevTools Coverage tab, reload the page, and sort by unused bytes
- Identify which scripts have the most unused code
- Analyze the bundle with a source map explorer (
source-map-explorer,webpack-bundle-analyzer, or Vite’srollup-plugin-visualizer) - For each problem:
- Switch from full-library imports to specific imports (
import debounce from 'lodash/debounce') - Add dynamic
import()for route-specific code - Configure Babel to target modern browsers and remove unnecessary polyfills
- Remove dead code manually
- Switch from full-library imports to specific imports (
- Rebuild and re-run Lighthouse
- Repeat
This process requires switching between multiple tools and significant knowledge of the build toolchain.
The Frontman Way
Tell Frontman to fix your Lighthouse issues. That is the entire workflow.
Frontman has a built-in Lighthouse tool. It runs the audit, reads the failing scores, fixes the underlying code, and re-runs the audit to verify the score went up. If issues remain, it keeps going — iterating through fixes and re-checks until the metrics pass. You do not dig through bundle analyzers or the Coverage tab. You say “fix the Lighthouse issues on this page” and Frontman handles the rest.
Key Fixes
- Code split by route — Use dynamic
import()so each page only loads its own code. Next.js, Remix, and Vite handle route-level splitting automatically, but shared component bundles may still need manual splitting - Use specific imports —
import { debounce } from 'lodash-es'instead ofimport _ from 'lodash'. Better yet, uselodash-eswhich is tree-shakeable - Remove unused polyfills — Update your
browserslistconfig to target only browsers you actually support. Use@babel/preset-envwithuseBuiltIns: 'usage'to include only needed polyfills - Enable tree shaking — Use ES modules (
import/export) so your bundler can remove unused exports. Mark packages as side-effect-free inpackage.jsonwith"sideEffects": false - Lazy-load third-party scripts — Load analytics, chat widgets, and ad scripts after the page is interactive
- Audit your dependencies — Use bundlephobia.com to check package sizes before adding them. Use
source-map-explorerto visualize what is in your bundle
People Also Ask
How much unused JavaScript is too much?
Lighthouse flags any script where a significant portion goes unused. As a rule of thumb, if more than 20% of a script’s bytes are unused, investigate. Scripts over 50 KB with more than 50% unused code should be split or replaced.
Does server-side rendering help with unused JavaScript?
SSR helps FCP and LCP because the browser receives pre-rendered HTML. But the same JavaScript still ships for hydration. To reduce unused JS in SSR apps, use React Server Components, partial hydration, or island architecture (like Astro).
What is the difference between unused JavaScript and unminified JavaScript?
Unminified JavaScript means the file contains whitespace, comments, and long variable names that add bytes. Unused JavaScript means the file contains code that downloads but never executes. They are separate issues — code can be minified but still unused.
Does dynamic import() increase the number of network requests?
Yes. Each dynamic import creates a separate chunk that loads on demand. This trades fewer initial bytes for more requests later. With HTTP/2 multiplexing, this tradeoff almost always favors splitting.
You can use Frontman to automatically fix this and any other Lighthouse issue. Frontman runs the audit, reads the results, applies the fixes, and verifies the improvement — all inside the browser you are already working in. Get started with one install command.