Skip to main content

Unused JavaScript.

Performance Core Web Vitals & Page Load

JavaScript that's downloaded but never executed — wastes bandwidth

What does this check test?

This check identifies JavaScript code that is downloaded and parsed by the browser but never executed during page load. Modern web applications frequently ship large JavaScript bundles containing code for features the user has not yet accessed — routes they have not visited, components not rendered on the current page, and polyfills for browsers they are not using. Chrome DevTools Coverage panel shows exact byte-level usage of every JavaScript file, typically revealing 40-70% of downloaded JavaScript is unused on any given page.

Why does it matter?

Unused JavaScript wastes bandwidth (critical on mobile networks), increases parse and compile time on the main thread (contributing to TBT), and consumes device memory. Every kilobyte of JavaScript costs more than a kilobyte of an image because it must be downloaded, parsed, compiled, and kept in memory — not just decoded. Studies show that JavaScript bytes are 2-3x more expensive than image bytes in terms of processing time. Removing unused JavaScript directly improves TBT, TTI, and can improve LCP when the main thread is saturated.

Who is affected?

Single-page applications (SPAs) built with React, Angular, or Vue are the most affected because they often ship the entire application as a single bundle. Sites using large utility libraries (lodash, moment.js) where only a few functions are used, sites with many npm dependencies, and sites that include polyfills for all browsers regardless of the visitor's browser are common offenders.

Where does this apply?

Use Chrome DevTools Coverage panel (Ctrl+Shift+P > 'Show Coverage') to see per-file usage percentages. The Sources panel shows unused code highlighted in red. Common sources of unused JavaScript: framework code for unused features, imported-but-unused library functions, route bundles for other pages, polyfills for modern browser features, and dead code from refactoring that was never removed.

How to fix it

Implement code splitting to load JavaScript on demand per route, or use your framework's built-in route-based splitting (Next.js, Nuxt, SvelteKit do this automatically). Import only what you need for tree-shaking:
js
// Bad — imports the entire library
import _ from 'lodash';

// Good — imports only the function you use
import { debounce } from 'lodash-es';
Dynamically import heavy modules:
js
// Load chart library only when needed
const renderChart = async (data) => {
  const { Chart } = await import('chart.js');
  new Chart(canvas, { data });
};
Replace large libraries with smaller alternatives (date-fns instead of moment.js, fetch instead of axios). Configure your bundler's `sideEffects` field in package.json to enable aggressive tree-shaking. Use `@babel/preset-env` with `useBuiltIns: 'usage'` to only include polyfills the target browsers actually need. Analyze your bundle with `webpack-bundle-analyzer` or `source-map-explorer` to identify the largest unused modules.

References

AppVet checks Unused JavaScript automatically

Run a free performance scan and get a full report with actionable fixes, including a Fix with AI prompt you can paste into any coding tool.

Run Audit