Website problems

Heavy JavaScript

JavaScript is the most expensive kind of byte a page can carry. An image is downloaded and decoded; a script is downloaded, parsed, compiled and executed, and the execution happens on the main thread, where it blocks everything else including responses to taps. A megabyte of JavaScript therefore costs substantially more than a megabyte of image, and the cost falls hardest on the low-end devices least able to absorb it.

Why script bytes cost more

Download is the part everyone measures, and on a modern connection it is often the smallest component.

Parsing and compiling happen before anything runs, and they scale with the size of the file regardless of how much of it is used.

Execution occupies the main thread. While a script runs, the browser cannot paint, cannot respond to input, and cannot run other scripts — which is why a page can appear loaded and ignore taps.

Memory is retained afterwards, which on a device with limited RAM means other tabs are evicted and returning to the page reloads it.

The device gap is the important part: the same bundle that parses in 100 milliseconds on a current laptop can take well over a second on a mid-range phone several years old.

Where bundles grow

Libraries imported whole for one function. A date library, an icon set, a utility collection — each adds its full weight unless the build can eliminate the unused parts.

Polyfills shipped to browsers that do not need them, which is most of them.

Duplicated dependencies: two versions of the same library pulled in by two packages, both bundled.

Everything loaded on every route. A single bundle containing the checkout, the account area and the admin interface is downloaded by someone reading an article.

Third-party tags, which are outside the build entirely and therefore outside every bundle-size budget.

Framework overhead, which is a fixed cost paid on the first page and is worth knowing rather than worth panicking about.

How to check it yourself

In the Network panel, filter by JS and read the total transferred. Then read the uncompressed total, because that is what gets parsed.

In the performance panel, record a load and look at the main-thread activity. Long tasks — blocks over 50 milliseconds — are where the page stopped responding.

The coverage tool reports how much of each script was actually executed. A bundle with 20% coverage on the landing page is mostly code for somewhere else.

Throttle the CPU to four or six times slower and reload. That approximates a mid-range phone, and it is the measurement that matches most visitors.

How to reduce it

Split by route. Code for the checkout should be downloaded when someone reaches the checkout, not when they read a blog post. This is usually the largest single reduction available.

Import what you use. Named imports from a library that supports tree shaking cost the functions you name; a default import of the whole package costs all of it.

Replace large dependencies where a smaller one or a platform API exists. Date formatting, HTTP requests and DOM utilities all have native equivalents now.

Deduplicate. A bundle analyser will show the same library included twice more often than anyone expects.

Drop polyfills for browsers you no longer support, and serve modern syntax to browsers that understand it.

Audit the third parties, which are outside the build and frequently larger than everything in it.

What this does to Core Web Vitals

Interaction to Next Paint measures the delay between a user's action and the next frame. Long main-thread tasks are its main cause, and long tasks are mostly JavaScript.

Largest Contentful Paint suffers when the largest element is rendered by script rather than present in the HTML, because the paint waits for download, parse and execution.

Cumulative Layout Shift suffers when script inserts content into the flow after the initial paint.

So heavy JavaScript is not one metric's problem. It is the common cause behind all three, which is why reducing it moves more than any single targeted fix.

How VeriFixScan detects it

`performance.heavy_javascript` reports the individual script files on each crawled page that are large enough to matter, with their sizes and URLs.

`performance.javascript` reports the totals per page — count and transferred weight — so a page with one large bundle and a page with forty small ones are distinguishable.

`performance.third_party_resources` separates the scripts served from other origins, which are the ones outside your build.

`performance.core_web_vitals` reports the measured outcome, so the weight and its consequence appear together.

Frequently asked questions

How much JavaScript is too much?
There is no threshold. The useful comparison is how much of it executes before the page becomes usable, and how long the main thread is blocked on a mid-range phone rather than on a developer's machine.
Does minifying fix heavy JavaScript?
It reduces transferred bytes. Parse and execution cost scale with the code that remains, so minification helps the download and not the work. Sending less code is what reduces the work.
Why is my site fast on desktop and slow on mobile?
Parsing and executing JavaScript is CPU-bound, and the gap between a laptop and a mid-range phone is large. Throttling the CPU four to six times reproduces it.

Sources

Related

VeriFixScan crawls a site and applies its checks to every page it reaches, keeping the evidence behind each finding. Scanning one website is free.

Scan a website