Quick Answer

Measure before changing anything, then work in order of impact: server response time and hosting location, render-blocking CSS and JavaScript, image size and format, total JavaScript payload, and layout stability. For most sites the largest single win is not code at all — it is reducing the distance between the server and the visitor, usually with a CDN.

Measure Before You Optimise

Performance work without measurement is guesswork, and the bottleneck is rarely where people assume.

The three metrics that matter — Google's Core Web Vitals, which also affect search ranking:

  • Largest Contentful Paint (LCP) — when the main content appears. Target under 2.5 seconds.
  • Interaction to Next Paint (INP) — how quickly the page responds to input. Target under 200 milliseconds.
  • Cumulative Layout Shift (CLS) — how much the page jumps around while loading. Target under 0.1.

Tools to use: PageSpeed Insights for a scored report with real-user data where available; Chrome DevTools Lighthouse for local audits; and the Network tab for what is actually being downloaded and in what order.

Test on a throttled connection. DevTools can simulate slow 4G. Your site on office broadband tells you almost nothing about the experience on a mid-range phone on mobile data, which is most of your Indian audience.

One measurement to take first, because it separates two entirely different problems:

curl -s -o /dev/null -w 'ttfb=%{time_starttransfer}s total=%{time_total}s\n' https://yoursite.com/

A slow first byte with a fast total means the server is the problem. A fast first byte with a slow total means the browser is — render-blocking resources, heavy JavaScript, unoptimised images.

Start With the Server, Not the Code

This is where the biggest wins usually are, and where developers spend the least time because it feels less like programming.

Time to first byte is how long the server takes to start responding. If it is over a second, no amount of frontend work will make the site feel fast — everything else waits behind it.

The causes are usually distance and hosting. A server in one country serving visitors in another pays the round-trip cost on every request, including the TLS handshake, which alone can be a large share of the total.

A CDN is the highest-leverage change for most sites. It serves content from a location near the visitor and terminates TLS there, which removes most of the connection cost. Free tiers exist and setup is a nameserver change rather than a code change.

Enable compression. Brotli or gzip typically reduces HTML, CSS and JavaScript by 70 percent or more. Check whether it is on:

curl -sI -H 'Accept-Encoding: br,gzip' https://yoursite.com/ | grep -i content-encoding

Set cache headers correctly. Content-hashed assets can be cached effectively forever; HTML should not be cached long or visitors see stale pages after a deploy. Getting this wrong in either direction causes real problems — one wastes bandwidth, the other serves outdated content.

Render-Blocking Resources

The browser cannot paint until it has the CSS, and a classic script pauses HTML parsing entirely. These two facts explain most of the remaining delay.

CSS blocks rendering by design. Painting before the stylesheets arrive would show unstyled content and then reflow violently. So a slow stylesheet delays the entire page appearing.

Keep the CSS that styles above-the-fold content small and load the rest asynchronously. Remove unused CSS — frameworks often ship far more than a page uses.

Scripts block parsing unless you tell them not to.

<script src="app.js"></script>                <!-- blocks parsing -->
<script src="app.js" defer></script>          <!-- parses on, runs after HTML -->
<script src="app.js" async></script>          <!-- runs as soon as it arrives -->

Use defer for anything needing the DOM, and async only for independent scripts such as analytics, since async execution order is unpredictable.

Third-party scripts are usually the worst offenders. Analytics, chat widgets, ad tags and font loaders often outweigh a site's own code. Audit them honestly and ask what each one earns. Loading them after the page is interactive is almost always acceptable.

Fonts deserve attention: use font-display: swap so text renders in a fallback immediately rather than staying invisible while the font downloads, and preconnect to the font host so the request starts sooner.

Images and JavaScript Payload

Images are usually the largest thing on a page and the easiest to fix.

  • Use modern formats. WebP typically saves 25 to 35 percent over JPEG at the same quality, with universal support now.
  • Serve the right size. A 3000px image displayed at 400px wastes most of its bytes. Resize at build time rather than scaling in CSS.
  • Lazy-load below-the-fold images with loading="lazy" — but never on the main above-the-fold image, since that delays your LCP.
  • Always set width and height. Without them the browser cannot reserve space, so content jumps when the image loads. This is the most common cause of poor CLS.
<img src="hero.webp" alt="..." width="1200" height="630">
<img src="below.webp" alt="..." width="800" height="600" loading="lazy">

JavaScript payload costs twice — downloading it, and then parsing and executing it, which is the expensive part on a mid-range phone.

Audit what you actually ship. A large library included for one function, an entire icon set for six icons, or a date library where Intl would do are all common. Code-split so a route only loads what it needs, and check whether a dependency is doing enough to justify its size.

The Order to Work In

If you do nothing else, do these in this sequence — they are ordered by impact per hour spent.

  1. Measure. Run PageSpeed Insights and check TTFB separately. Know whether your problem is the server or the browser before touching anything.
  2. Put a CDN in front of the site if visitors are far from your server. Usually the single largest win, and it is configuration rather than code.
  3. Enable compression and correct cache headers. Minutes of work, large effect.
  4. Fix images. Convert to WebP, resize to display size, add width and height, lazy-load below the fold.
  5. Defer non-critical JavaScript, especially third-party scripts.
  6. Trim the JavaScript bundle. Remove or replace oversized dependencies, and code-split by route.
  7. Fix layout shift. Dimensions on images and embeds, reserved space for anything that loads late.

What not to spend time on until the above is done: micro-optimising loops, obsessing over framework choice, or chasing a perfect Lighthouse score. A score of 100 on a page nobody can reach quickly is worth less than a score of 85 served from nearby with small images.

And re-measure after each change. Performance work done without verification frequently makes things worse — a lazy-loaded hero image being the classic example.

Frequently Asked Questions

What is the biggest cause of a slow website? Usually server response time and distance from the visitor, followed by unoptimised images and excessive JavaScript. Check time to first byte separately — if it is over a second, frontend work will not make the site feel fast.
Does a CDN really help that much? For visitors far from your origin server, yes — often more than every code change combined. It serves content from a nearby location and terminates TLS there, removing most of the connection cost including the handshake.
Should I lazy-load all images? No. Never lazy-load the main above-the-fold image, because that delays your Largest Contentful Paint — the opposite of the intended effect. Lazy-load only images below the initial viewport.
Why does my page jump around while loading? Elements without reserved space, most often images and embeds missing width and height attributes. Set explicit dimensions so the browser can allocate space before the resource arrives.
Do Core Web Vitals affect SEO? Yes, they are a ranking signal, though content relevance matters more. The practical argument is stronger than the ranking one — slow pages lose visitors before they read anything, particularly on mobile connections.