Scripts per page
How many scripts the page runs and their over-the-wire weight.
At a glance the headline numbers for Scripts per page
How many scripts the page runs and their over-the-wire weight.
The typical page runs 26 scripts weighing 552 KB.
Scripts per page — n the value at each percentile across all sites
Scripts per page — n 26. p75 49. p99 156. computed
Scripts per page — size the value at each percentile across all sites
Scripts per page — size 552 KB. p75 1,007 KB. p99 3.7 MB. computed
Why this matters for the Core Web Vitals, and where to start fixing it
Script weight is the most expensive weight. A kilobyte of JavaScript costs more than a kilobyte of image, because after the download it is parsed, compiled and executed on the main thread. That is the same thread that must answer every click and keystroke, which is why script totals track INP.
The count matters next to the bytes: every script is a potential long task and another spot for the main thread to stall. Most pages would lose nothing by deferring most of their scripts. The ones that truly must run early are rare.
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (4) — admin only
SELECT COUNT(*) AS count,
quantile_disc(m.scripts.total.n, 0.10) AS p10,
quantile_disc(m.scripts.total.n, 0.25) AS p25,
quantile_disc(m.scripts.total.n, 0.50) AS p50,
quantile_disc(m.scripts.total.n, 0.75) AS p75,
quantile_disc(m.scripts.total.n, 0.90) AS p90,
quantile_disc(m.scripts.total.n, 0.99) AS p99
FROM sites WHERE m.scripts.total.n IS NOT NULL;
SELECT CASE WHEN m.scripts.total.n >= 5 AND m.scripts.total.n < 10 THEN 0 WHEN m.scripts.total.n >= 10 AND m.scripts.total.n < 15 THEN 1 WHEN m.scripts.total.n >= 15 AND m.scripts.total.n < 20 THEN 2 WHEN m.scripts.total.n >= 20 AND m.scripts.total.n < 25 THEN 3 WHEN m.scripts.total.n >= 25 AND m.scripts.total.n < 30 THEN 4 WHEN m.scripts.total.n >= 30 AND m.scripts.total.n < 35 THEN 5 WHEN m.scripts.total.n >= 35 AND m.scripts.total.n < 40 THEN 6 WHEN m.scripts.total.n >= 40 AND m.scripts.total.n < 45 THEN 7 WHEN m.scripts.total.n >= 45 AND m.scripts.total.n < 50 THEN 8 WHEN m.scripts.total.n >= 50 AND m.scripts.total.n < 55 THEN 9 WHEN m.scripts.total.n >= 55 AND m.scripts.total.n < 60 THEN 10 WHEN m.scripts.total.n >= 60 AND m.scripts.total.n < 65 THEN 11 WHEN m.scripts.total.n >= 65 AND m.scripts.total.n < 70 THEN 12 WHEN m.scripts.total.n >= 70 AND m.scripts.total.n < 75 THEN 13 WHEN m.scripts.total.n >= 75 AND m.scripts.total.n < 80 THEN 14 WHEN m.scripts.total.n >= 80 THEN 15 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."desktop".cls, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."desktop".cls IS NOT NULL AND crux."desktop".cls <= 0.1) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."desktop".cls IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.scripts.total.n IS NOT NULL GROUP BY bucket_idx;
SELECT COUNT(*) AS count,
quantile_disc(m.scripts.total.size, 0.10) AS p10,
quantile_disc(m.scripts.total.size, 0.25) AS p25,
quantile_disc(m.scripts.total.size, 0.50) AS p50,
quantile_disc(m.scripts.total.size, 0.75) AS p75,
quantile_disc(m.scripts.total.size, 0.90) AS p90,
quantile_disc(m.scripts.total.size, 0.99) AS p99
FROM sites WHERE m.scripts.total.size IS NOT NULL;
SELECT CASE WHEN m.scripts.total.size >= 0 AND m.scripts.total.size < 200 THEN 0 WHEN m.scripts.total.size >= 200 AND m.scripts.total.size < 400 THEN 1 WHEN m.scripts.total.size >= 400 AND m.scripts.total.size < 600 THEN 2 WHEN m.scripts.total.size >= 600 AND m.scripts.total.size < 800 THEN 3 WHEN m.scripts.total.size >= 800 AND m.scripts.total.size < 1000 THEN 4 WHEN m.scripts.total.size >= 1000 AND m.scripts.total.size < 1200 THEN 5 WHEN m.scripts.total.size >= 1200 AND m.scripts.total.size < 1400 THEN 6 WHEN m.scripts.total.size >= 1400 AND m.scripts.total.size < 1600 THEN 7 WHEN m.scripts.total.size >= 1600 AND m.scripts.total.size < 1800 THEN 8 WHEN m.scripts.total.size >= 1800 THEN 9 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."desktop".cls, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."desktop".cls IS NOT NULL AND crux."desktop".cls <= 0.1) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."desktop".cls IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.scripts.total.size IS NOT NULL GROUP BY bucket_idx;