# How to speed up a website: the order that pays

Most speed advice is a list of thirty items with no order. On a small product site, six changes account for nearly all the gain, and they have a sensible sequence. Measure first, work down the list, and check the field data four weeks later.

Updated 2026-09-15 · Source: https://porteur.ai/guides/how-to-speed-up-a-website

## Measure first, and measure the right thing

Two kinds of number exist and they answer different questions. Field data is what real Chrome users experienced, at the 75th percentile over 28 days, and it is what Google uses. Lab data is one simulated run on a mid-range phone over a throttled connection, and it is what tells you why.

- Largest Contentful Paint: good up to 2.5 s, poor above 4 s. The big thing at the top of the page.
- Cumulative Layout Shift: good up to 0.1, poor above 0.25. The page moving under a reader's thumb.
- Interaction to Next Paint: good up to 200 ms, poor above 500 ms. The wait after a tap.

Open PageSpeed Insights on the page you care about. The top half is the field assessment, the half that counts. The bottom half is a Lighthouse run with the opportunities. Write down the three vitals before you touch anything, because you will want them in four weeks.

> The Lighthouse score is a diagnostic, not a target. It varies between runs, it weights Total Blocking Time at 30%, LCP at 25%, CLS at 25%, and it is not a ranking signal. The field vitals are.

## The order of work

| Change | What it moves | Effort |
| --- | --- | --- |
| The hero image | LCP, often by seconds | An hour |
| Render-blocking CSS and JavaScript | First paint, and LCP behind it | An afternoon |
| Fonts | First paint, and CLS when they swap | An hour |
| Third-party scripts | INP, total blocking time, and the paint | An hour to decide, minutes to remove |
| The server and the CDN | Time to first byte, which every other number inherits | A day, once |
| The JavaScript bundle | INP and blocking time | The longest job, do it last |

Work top to bottom and re-measure after each. A page that was poor is usually fine after the first three, and the last two are where the remaining seconds hide.

## The hero image, the single biggest win

On most marketing pages the largest element is an image at the top. It is the LCP element, and three mistakes make it slow.

1. **Never lazy-load it** loading="lazy" on the element above the fold delays the very thing being measured. Lazy loading is for what is below.
2. **Give it priority** fetchpriority="high" on the hero image tells the browser to fetch it before the rest. If it is a CSS background, preload it, because the browser cannot see it in the HTML.
3. **Serve the right size and format** AVIF or WebP, with srcset and sizes so a phone does not download a desktop image. A hero that weighs a few hundred kilobytes instead of two megabytes paints seconds earlier.
4. **Reserve its space** width and height attributes, or an aspect-ratio in CSS, so nothing jumps when it arrives. That is the CLS half of the same fix.

```html
<img src="/hero.avif"
     width="1200" height="630"
     fetchpriority="high"
     alt="The report open on a laptop">
```

## Render-blocking CSS and JavaScript

A stylesheet in the head stops the browser painting until it arrives. A synchronous script stops it parsing. Lighthouse lists both under render-blocking resources, and the fix is mostly attributes.

- Add defer to scripts that do not need to run before the paint, which is nearly all of them. Modules defer by default.
- Inline the small amount of CSS the first screen needs, and load the rest without blocking.
- Remove the CSS nobody uses. A framework shipped whole on a page using a tenth of it is the usual finding.
- Avoid @import in stylesheets: it serialises requests that could have run in parallel.

## Fonts: one family, self-hosted, loaded first

A web font from a third-party host costs a DNS lookup, a connection, a stylesheet and then the font file, all before the first word appears. Self-hosting removes three of the four.

- Self-host the files in WOFF2 and serve them from your own domain or CDN.
- font-display: swap so text is readable while the font loads, with a fallback whose metrics are matched so the swap does not shift the layout.
- Preload only the one face used above the fold. Preloading everything is the same as preloading nothing.
- Subset to the characters you use, and prefer one variable font to four static weights.
- A system font stack costs nothing at all, and on a product site nobody notices.

## Third-party scripts, the weight you did not write

1. **List what is on the page** Lighthouse has an audit for the impact of third-party code. Most small sites find analytics, a chat widget, a consent tool, a video embed and a tag manager.
2. **Remove what nobody reads** The fastest script is the one you delete. A chat widget nobody answers and a heatmap tool from last year are both pure cost.
3. **Delay what can wait** Analytics can start when the browser is idle. A page view captured a second later is the same page view.
4. **Use a facade for embeds** A video embed loads a player and a tracking bundle before anyone presses play. A thumbnail that loads the real embed on click saves all of it.
5. **Preconnect to what must load early** For the few origins that are genuinely needed on the first screen, a preconnect saves the handshake.

## The server and the CDN

Time to first byte is the delay every other metric inherits. It includes redirects, the lookup, the handshakes and your server's own work, and it is the one number a CDN fixes almost entirely for distant visitors.

- Put a CDN in front of the origin. It serves from the location closest to the visitor and removes most of the first-byte time.
- Cache the HTML where you can: a short cache with revalidation, or a stale-while-revalidate window at the edge. Static pages should never be rebuilt per request.
- Give hashed static assets a year of immutable caching. They never change, and the hash changes when they do.
- Serve Brotli for text, gzip as the fallback.
- Enable HTTP/2, and HTTP/3 where the CDN offers it. Both are a setting, not a code change.
- Remove redirect chains on the entry points. Two hops before the first byte is two round trips a visitor waits through.

## The JavaScript bundle, last and longest

This is where the remaining Interaction to Next Paint lives. It is also the work that takes weeks rather than hours, which is why it comes last: the five changes above usually take a page from poor to good on their own.

- Ship less of it: split by route so a landing page does not load the dashboard's code.
- Render the content on the server so the browser is not building the page and hydrating it at once.
- Break long tasks so the main thread is free when someone taps.
- Keep the DOM small. A page with tens of thousands of nodes is slow to interact with whatever the bundle weighs.

## How to tell whether it worked

1. **Re-run the lab test immediately** Same page, same tool. The lab number should move the moment you deploy. Run it twice: scores vary between runs.
2. **Wait for the field data** The field assessment is a 28-day window of real visits. Nothing you changed today is fully reflected until four weeks of visits have passed.
3. **Read the Core Web Vitals report** In Search Console, the report groups URLs by template. A group moving from Needs improvement to Good is the fix landing across every page built from that template.
4. **Keep a note of what you changed and when** Without dates you cannot attribute the movement, and in four weeks you will not remember the order.

A fixed page looks like this: LCP under 2.5 s in the field, CLS near 0.1, INP under 200 ms, and a lab report whose remaining opportunities are worth less than an hour each.

## Questions

### Does page speed affect rankings?

Core Web Vitals are a ranking signal, measured on field data at the good thresholds, and Google has said it is a smaller factor than relevance and content quality. Speed also affects conversion and crawling, which is why it is worth an afternoon regardless.

### What is a good Lighthouse score?

The score is a diagnostic. It varies between runs and is not what Google ranks on. Aim for the field thresholds instead: LCP up to 2.5 s, CLS up to 0.1, INP up to 200 ms.

### Why is my score good on desktop and poor on mobile?

The mobile test simulates a mid-range phone on a throttled connection, and Google indexes the mobile version of pages. A page that is fine on a laptop can be slow on a phone because of CPU, JavaScript and images sized for a large screen.

### How long before Google sees my speed improvements?

The lab numbers change immediately. The field assessment uses a 28-day window of real visits, so the reports in Search Console take about four weeks to reflect a fix fully.

### Do I need a CDN for a small site?

If your visitors are far from your server, yes: it removes most of the time to first byte, and most hosting platforms include one. If everything is cached and your audience is local, it matters less.

### What single change usually helps the most?

The hero image. It is the largest element on most pages, so it is what Largest Contentful Paint measures, and the three fixes (do not lazy-load it, give it priority, serve a modern format at the right size) take about an hour.

## Read next

- [Core Web Vitals for a product site: the three numbers](https://porteur.ai/guides/core-web-vitals): The product founder’s guide to LCP, CLS and INP: what Google measures, why phones decide the pass, common causes, and how to test and fix.
- [Largest Contentful Paint: what slows it and what fixes it](https://porteur.ai/guides/largest-contentful-paint): See what usually counts as LCP, what makes it slow, how to fix it in order, and how to read it in Lighthouse and field data.
- [Render-blocking resources: what blocks the first paint and how to unblock it](https://porteur.ai/guides/render-blocking-resources): Stop CSS and synchronous scripts from blocking first paint. Read the Lighthouse audit and fix in order: defer, inline critical CSS, split CSS, and handle fonts.
- [Web fonts and page speed: load one face, and load it first](https://porteur.ai/guides/web-fonts-and-page-speed): Ship crisp type without slowing first paint or shifting layout. Choose one fast path, preload the face above the fold, and stop the swap from moving text.
- [Third-party scripts: the page speed you gave away](https://porteur.ai/guides/third-party-scripts-and-page-speed): See what each third-party script costs and what to do: remove, load on interaction, defer, self-host, facade video and maps, and preconnect smartly.
- [Image optimisation for page speed: the hero image and everything below it](https://porteur.ai/guides/image-optimisation-for-page-speed): Fix the hero image first for LCP, then lazy-load the rest. Choose AVIF or WebP, set srcset and sizes, and add width and height to stop shift.
- [How to read PageSpeed Insights: field data first, then the score](https://porteur.ai/guides/how-to-read-pagespeed-insights): Start with field data, not the score. Learn what Google uses, why scores vary, and how to turn a PageSpeed Insights run into a clear order of fixes.
- [Core Web Vitals checker](https://porteur.ai/tools/core-web-vitals-checker): Paste a URL for one Lighthouse run on a simulated phone: LCP, CLS, TBT and FCP against Google's thresholds, the biggest savings, the failing audits.

Paste your URL and the free check measures your home page the way Google does, on a phone, and names the three changes that would give back the most time. Free check: https://porteur.ai/
