Website Performance & Core Web Vitals

Removing Unused JavaScript

Unused JavaScript is code the browser downloads, parses and runs for a page that never needs it. It does not bloat your download alone, it ties up the main thread and slows the Core Web Vitals that Google watches. Here is how to find it and remove it.

Junaid KhalidUpdated 9 min readAdvancedIncludes a 2 min video

The short answer

Remove unused JavaScript in four moves. Audit the page with Chrome DevTools Coverage and the Lighthouse Reduce unused JavaScript report. Tree-shake the code nothing imports. Code-split the code you do use so each page ships only what it needs on load. Defer or drop third-party scripts. The payoff is faster Largest Contentful Paint and Interaction to Next Paint, which are part of Google's page experience signals.

Set expectations honestly: this is a speed and experience fix, not a magic ranking lever. It removes a handicap rather than buying a boost, and the gain shows up in field Core Web Vitals, not just a lab score.

  • Audit before you cut: Coverage shows used versus unused bytes per file.
  • Dead code is tree-shaken; live but non-critical code is code-split. Different problems, different fixes.
  • Judge the result on real-user INP and LCP, not on a perfect Lighthouse number.

What Counts as Unused JavaScript

Unused JavaScript comes in two shapes, and telling them apart decides how you fix it.

Dead code is shipped to the browser but never runs anywhere in your app: an old helper nobody calls, a utility library where you use one function, a feature you removed from the UI but not from the bundle. This is waste with no upside, and tree shaking exists to delete it.

Code used elsewhere, but not here is live and valuable, just not on this page or not at first paint: the checkout logic on your homepage, a charting library behind a tab, a date picker only the booking page opens. The browser should not pay for it until it is needed, which is what code splitting and deferred loading arrange.

Either way, the cost is the same. Every script is downloaded, then parsed, compiled and executed on the main thread, the single thread the browser also uses to paint the page and react to input. A big block of JavaScript turns into a long task, and while a long task runs, the page cannot respond to a tap. That is the mechanism behind the metrics below.

How Unused JavaScript Affects SEO

The link between JavaScript and ranking is indirect, and it helps to be precise about it. Google does not rank pages on bundle size. What it uses, as part of its page experience signals, is Core Web Vitals, and JavaScript on the main thread is one of the biggest things that drags two of them down.

Interaction to Next Paint (INP) measures how quickly the page responds to a tap, click or key press across the whole visit. Long JavaScript tasks are the usual reason a page feels stuck after you touch it, so trimming them is the most direct way to improve INP. INP replaced First Input Delay as a Core Web Vital in March 2024, and it is less forgiving, because it looks at every interaction, not just the first.

Largest Contentful Paint (LCP) measures how long the main content takes to appear. Render-blocking scripts in the head, and heavy scripts that compete for the main thread during load, push LCP out.

Google has described page experience as a tiebreaker: when several pages are comparably relevant and helpful, the better experience can win. So removing unused JavaScript is worth doing, but it works as support for good content, not a substitute for it. The more reliable win is the human one: a page that responds instantly keeps more of the visitors your rankings already earned. If a drop in clicks sent you here, our guide to why Google rankings drop helps you check whether speed is actually the cause before you rebuild the bundle.

Audit First, Then Cut

Never delete scripts by guesswork. Two free Chrome tools tell you exactly which bytes are wasted, in this order.

  1. 1

    Record a Coverage report

    In Chrome DevTools open the Coverage tab, press reload, then click the page's main interactions. The table shows each file's total bytes and how many went unused. Sort by unused bytes to find the worst offenders.

  2. 2

    Run the Lighthouse audit

    Run Lighthouse on the same page and read the Reduce unused JavaScript opportunity. It names the scripts and estimates the kilobytes you could save, which is a fast way to rank the work.

  3. 3

    Separate dead code from deferred code

    For each offender decide: is this code never used (tree-shake or delete it) or used elsewhere but not here (code-split or defer it). The two problems have different fixes, and mixing them up wastes effort.

  4. 4

    Fix, then measure in the field

    Apply the fix, re-run Coverage to confirm the unused bytes dropped, then watch real INP and LCP in the Core Web Vitals report of Search Console or the CrUX data. Lab scores move first; field data is what Google uses.

The Chrome team walks through the DevTools Coverage tool on a real page in under three minutes, reading the used and unused bytes of each file.Video: Load your page faster: remove unused code by Chrome for Developers. Loads from YouTube only when you press play.

Four Ways to Shrink the Payload

Match the technique to the problem the audit found. Dead code and deferrable code need different tools.

TechniqueWhat it removesHow to apply it
Tree shakingDead code that nothing importsShip ES modules, use named imports instead of whole-library imports, set sideEffects in package.json, and build in production mode where tree shaking is on by default in webpack and Vite.
Code splitting and dynamic importsLive code the first paint does not needLoad heavy or below-the-fold components on demand. In Next.js use next/dynamic; in plain React use React.lazy with Suspense. Keeps charts, editors and modals out of the initial bundle.
Defer and async third-party scriptsRender-blocking executionAdd defer to non-critical scripts and async to ones that do not depend on DOM order. Never load analytics, chat or experiment scripts synchronously in the head of the document.
Audit and prune dependenciesHeavy libraries used for one small thingImport the one function you need, not the whole package. Swap an oversized library for a lighter one, and remove tags from vendors you no longer use. A bundle analyzer shows which packages are worth the fight.

One note for framework users. In Next.js and most modern setups, page-level code splitting and production tree shaking are already on, so the wins are usually in three places: a few oversized dependencies, components that should be dynamically imported, and third-party tags loaded too eagerly. On WordPress the pattern is different: the bloat is plugin and theme scripts loaded site-wide, which an asset-cleanup plugin can scope to the pages that use them. For the reverse side of this work, see browser caching and compression, which makes the code you do keep cheaper to deliver.

A Worked Example

Illustrative scenario, not client data

A marketing site built on Next.js fails the Reduce unused JavaScript audit on its homepage, and INP is in the needs-improvement band on phones. The team wants to delete scripts. The audit changes the plan.

  1. Coverage: on the homepage, most of the main bundle's bytes go unused on load. The three biggest contributors are a charting library, a date picker, and an analytics and session-replay SDK.
  2. Classify each one: the chart only appears on the pricing page, so it is live but not needed here. The date picker is left over from a removed feature, so it is dead. The analytics SDK is used, but it does not need to run before the page is interactive.
  3. Chart: load it with a dynamic import so it is fetched only on the pricing page, not in the homepage bundle.
  4. Date picker: remove the dependency. Tree shaking cannot drop it while a stray import still references it, so the import is deleted too.
  5. Analytics SDK: move it to load after the page is interactive, so it no longer competes with the first paint.

Re-running Coverage shows the homepage bundle is much lighter, and over the next few weeks the field INP for the page moves into the good band. Notice the shape of the fix: one dynamic import, one deleted dependency, one deferred tag. The first instinct, delete everything, would have broken the pricing page's chart. The audit is what turned a risky purge into three safe, targeted edits.

Did the speed work move search?

Murkuz connects Google Search Console, Analytics 4 and Bing Webmaster Tools to Claude or ChatGPT, read-only. After you ship a performance fix, ask Search_Analytics for the affected pages' clicks and positions before and after, or point Landing_Page_Diagnosis at one page to see how it is found and how it performs. It reads your data; it does not touch your code.

See the Search Console connector

Common Mistakes

  • Removing code that is actually used

    Coverage marks a file unused if its code did not run during your recording. If you never clicked the menu, its script looks dead. Exercise the page's real interactions before you cut anything, and re-test after.

  • Lazy-loading critical above-the-fold code

    Deferring the JavaScript that renders the hero or the main content trades an unused-JS warning for a slower LCP. Defer what is below the fold or behind an interaction, not what the visitor sees first.

  • Chasing a perfect Lighthouse score

    A lab score of 100 on your laptop does not mean fast for real users on mid-range phones. Optimise for field INP and LCP, and treat Lighthouse as a to-do list, not the goal.

  • Minifying instead of removing

    Minification and compression shrink the bytes on the wire, but the browser still parses and executes the code. Unused code that is merely minified still runs long tasks. Remove or defer it, do not just compress it.

Unused JavaScript is one input to Core Web Vitals, not the whole story. Our guides to optimizing INP, improving LCP and minimizing CLS cover the rest, and measuring PageSpeed explains how to read lab and field numbers together.

Further reading

The best material on finding and removing unused JavaScript, starting with Google's own documentation. Each one was read in full before it was added here.

  • Official docsChrome for Developers

    Reduce unused JavaScript

    The reference for the Lighthouse audit that flags this problem. It explains why even async unused code costs you, and lists fixes including code splitting, dead-code elimination and framework-specific lazy loading.

  • ReferenceChrome DevTools docs

    Coverage: find unused JavaScript and CSS

    How to open the Coverage tool, record a page load plus interactions, and read the per-file used and unused byte breakdown. This is the audit step the page tells you to run first.

  • Guideweb.dev, Jeremy Wagner

    Reduce JavaScript payloads with tree shaking

    Tree shaking explained as dead-code elimination over ES modules: use named imports, keep modules intact through the build, and declare sideEffects in package.json so the bundler can drop what you never call.

  • Guideweb.dev

    Code-split JavaScript

    A clear walkthrough of splitting a bundle with dynamic import() so a page ships only the code it needs on load, with configuration notes for webpack, Parcel, Rollup and esbuild.

  • Guideweb.dev, Houssein Djirdeh

    Remove unused code

    Focuses on auditing dependencies with the Network and Coverage tabs plus a bundle analyzer, then trimming with selective imports or by swapping a heavy library for a lighter one.

  • Official docsweb.dev, Jeremy Wagner and Barry Pollard

    Interaction to Next Paint (INP)

    The authoritative definition of INP, the Core Web Vital that JavaScript on the main thread hurts most. Covers the thresholds (200ms or less is good) and why long tasks delay the response to a click.

Frequently Asked Questions

How does unused JavaScript affect SEO?

Indirectly, through speed. JavaScript is parsed, compiled and executed on the browser's main thread, the same thread that renders the page and responds to taps and clicks. Code the page never uses still has to be downloaded and processed, which lengthens the long tasks that delay Largest Contentful Paint and Interaction to Next Paint. Those are Core Web Vitals, and Core Web Vitals are part of Google's page experience signals. Removing unused JavaScript will not rank a weak page, but a faster, more responsive page competes better against equals and gives visitors a reason to stay.

How do I find unused JavaScript on my site?

Use two free tools. In Chrome DevTools, open the Coverage tab (Command or Control, Shift, P, then type Coverage), reload the page and interact with it, and read the unused bytes column for each file. Anything well over half unused is a candidate to split or defer. Then run Lighthouse and read the Reduce unused JavaScript audit, which lists specific scripts with the kilobytes you could save. For a view of which packages dominate the bundle, use webpack-bundle-analyzer or Vite's rollup-plugin-visualizer.

What is tree shaking and how does it remove unused JavaScript?

Tree shaking is dead-code elimination performed by modern bundlers such as webpack, Rollup, Vite and esbuild. The bundler reads your import and export statements statically and drops any exported function, class or variable that nothing imports. Three things make it work: your code and dependencies use ES modules (import and export, not require), the packages declare sideEffects correctly in package.json, and the build runs in production mode where tree shaking is on by default. Favour named imports over importing a whole library so the bundler can see what is safe to remove.

How is code splitting different from tree shaking?

Tree shaking removes code that is never used anywhere in your app. Code splitting keeps code you do use but loads it only when it is needed, so a feature a visitor may never open does not weigh down the first paint. In Next.js, each page is split automatically; for a heavy component you add a dynamic import, for example dynamic(() => import('../components/HeavyChart')). In plain React the equivalent is React.lazy with Suspense. Use tree shaking to delete dead code and code splitting to defer live but non-critical code.

Does removing unused JavaScript directly improve Google rankings?

No single change does. Google uses Core Web Vitals as part of its page experience signals, which it has described as a tiebreaker between pages of similar relevance rather than a dominant factor. So faster JavaScript helps on the margin and, more reliably, improves the experience that keeps visitors and conversions. Treat it as removing a handicap rather than buying a boost, and measure the result in the field with real INP and LCP data, not only a lab Lighthouse score.

How do I reduce unused JavaScript on WordPress without coding?

Most of the bloat on a WordPress site comes from plugins and themes that load their scripts on every page whether or not they are used. An asset-management plugin lets you disable a plugin's JavaScript on the pages where that plugin does nothing, for example loading a contact-form or slider script only where the form or slider appears. Audit third-party tags too (chat widgets, analytics, A and B testing), and load the non-critical ones with defer or after the first interaction. Always re-test in the Coverage tool afterwards to confirm you did not remove something a page needs.

Shipped a speed fix? Check what search did.

Connect Google Search Console once and ask, from Claude or ChatGPT, whether the pages you optimised gained clicks and positions. Read-only, through the official APIs.