How to speed up your website

Measure with Core Web Vitals and fix the biggest bottleneck first: usually heavy images, missing caching and too much JavaScript. Modern image formats, compression, Cache-Control and a CDN cover most of it.

Updated 6 min read

Learning objectives

After reading this article you will be able to:

  • Measure site speed with LCP, INP and CLS
  • Optimize images, compression and caching with code that works
  • Check in the browser that each change actually helped
On this page

A slow website loses visitors before it shows anything. The trouble is that "slow" is vague: it can be a server that takes too long to respond, a 4 MB photo at the top, or a script that freezes clicks. Each cause has a different fix, and optimizing blindly usually spends time on things that do not matter.

The approach that works is always the same: measure, find the biggest bottleneck, fix one thing at a time and measure again. This guide follows that order and shows the code for each change.

Unoptimizedheavy images, no compressionnetworkserverdownloadLCPCachedrepeat visit: hashed files come from cacheLCPWith a CDNcache + CDN: served from the nearest pointLCPLCP: main content on screentime
Each fix shortens one step: caching cuts the download and a CDN shortens the distance to the visitor.

How do you measure website speed?#

Google summarizes the loading experience in three metrics called Core Web Vitals:

Metric What it measures Good
LCP (Largest Contentful Paint) When the largest visible element appears 2.5 s or less
INP (Interaction to Next Paint) How long the page takes to respond to clicks and taps 200 ms or less
CLS (Cumulative Layout Shift) How much the layout jumps while loading 0.1 or less

Each metric is evaluated at the 75th percentile of visits, split by mobile and desktop. A page passes only if all three are within target.

To measure, open Chrome DevTools, go to the Lighthouse tab and run an audit in mobile mode. The Network tab shows the size and time of every file, and that is where you find the culprit. Lighthouse runs a simulated test; for real visitor data, use the Core Web Vitals report in Search Console or PageSpeed Insights.

Write the numbers down before changing anything. Without them, you cannot tell whether anything improved.

How do you optimize images?#

Images are usually the largest share of a page's bytes. Four changes cover most cases:

  1. Modern format. AVIF and WebP are smaller than JPEG and PNG at the same visual quality. Offer both with a fallback.
  2. Responsive sizes. Do not send a 2000 px image to a phone that is 400 px wide.
  3. Declared dimensions. width and height reserve the space and prevent CLS.
  4. Lazy loading only below the fold.
html
<picture>
  <source type="image/avif"
    srcset="photo-480.avif 480w, photo-800.avif 800w, photo-1200.avif 1200w"
    sizes="(max-width: 600px) 400px, 800px">
  <source type="image/webp"
    srcset="photo-480.webp 480w, photo-800.webp 800w, photo-1200.webp 1200w"
    sizes="(max-width: 600px) 400px, 800px">
  <img src="photo-800.jpg" alt="Photo description" width="800" height="600" loading="lazy">
</picture>

The browser uses the first <source> whose format it supports and skips the rest. The <img> is the fallback.

What about the main image at the top?#

It is almost always the LCP element, so do not put loading="lazy" on it: the browser has to know where the image sits before it can decide to defer it, and that delays it. Ask for high priority instead:

html
<img src="hero-1200.webp" alt="Main banner" width="1200" height="600" fetchpriority="high">

fetchpriority="high" is a hint, not a command, but it makes the browser start downloading the image sooner. If the image comes from a CSS background-image, the browser discovers it late. In that case, add <link rel="preload" as="image" href="hero.jpg" fetchpriority="high"> to the <head>.

How do you compress HTML, CSS and JavaScript?#

Text compresses very well. The browser sends Accept-Encoding: br, gzip and the server answers with Content-Encoding: br (Brotli) or gzip, plus Vary: Accept-Encoding so caches store each version separately. Enable compression for HTML, CSS, JS, JSON and SVG.

Do not compress images, audio and video again: JPEG, WebP, PNG and MP4 are already compressed, and compressing them again just burns CPU and can even make the file larger.

After compression, ship less code:

  • Remove libraries you use for a single function.
  • Use defer on scripts that do not need to run before the page appears: <script src="app.js" defer></script>.
  • Split JavaScript per page so each page downloads only what it uses.

How do you set up browser caching?#

Someone who already visited your site should not download everything again. The Cache-Control header tells the browser how long it can reuse a file. The safest strategy has two rules.

Files with a hash in the name (like app.3f9a1c.js) that never change at the same URL are cached for a year:

http
Cache-Control: max-age=31536000, immutable

The HTML, which references those files, should always be revalidated:

http
Cache-Control: no-cache

Careful: no-cache does not mean "do not store". It means "store it, but ask the server before reusing it". To forbid any storage, the value is no-store. When you change a file, its hash changes, its URL changes and the old cache entry simply stops being used. The full explanation is in What is Cache-Control.

When does a CDN help?#

A CDN keeps copies of your static files in many places around the world and serves each visitor from the nearest one. That cuts latency and takes load off your server. The gain is larger when your audience is spread out or far from the server region, and smaller when everyone is close to it. Details in What is a CDN.

A CDN usually respects the Cache-Control you set, so the two changes add up: caching decides what can be reused, the CDN decides from where.

If your content does not change on every request, a static site is the simplest case: no code runs on the server for each visit, only ready-made files that can be cached.

How do you know it worked?#

  1. Reload the page with DevTools open on the Network tab. On the second load, hashed files should show as "(memory cache)" or "(disk cache)".
  2. Check a file's headers: Cache-Control and Content-Encoding should be present.
  3. Run Lighthouse again and compare LCP, INP and CLS with the numbers you wrote down.
  4. Track the effect on real visitors in Search Console, which takes days to reflect changes.

Common mistakes#

  • Putting loading="lazy" on the LCP image.
  • Forgetting width and height, which causes CLS.
  • Giving a long max-age to files without a hash: visitors stop seeing the new version.
  • Optimizing what is not heavy: confirm in the Network tab first.
  • Testing only on your fast computer and good connection.

How to do this on Square Cloud#

On Square Cloud, you deploy the site and control its files and code. Static sites have their own runtime, and every web application gets a *.squareweb.app subdomain with HTTPS and an automatic TLS certificate.

The network includes a global CDN based on Cloudflare, HTTP/3 and unlimited traffic, with no charge per bandwidth or per request (fair-use policy). That covers delivery, and the CDN honors the Cache-Control your application sends. Image optimization, cache headers and JavaScript remain your own adjustments, as described above.

To measure the result, every plan has cookieless web analytics with visits, routes, countries and status codes. Pro and Enterprise add p50/p95/p99 latency and HTTP logs. The Hobby plan starts at R$12.49 per month.

See how to publish your site in Website hosting.

Website hosting

Static and SSR sites with automatic TLS and a global CDN

Learn more

FAQs

What is a good load time for a website?

According to Google, an LCP of 2.5 seconds or less, an INP of 200 ms or less and a CLS of 0.1 or less count as good, measured at the 75th percentile of visits.

What slows a website down the most?

Usually oversized images, files served without caching or compression, and too much JavaScript blocking the page. Measure before changing anything to see which one matters most for your site.

Do I need a CDN for a small website?

It helps when visitors are far from your server, because static files are served from a closer location. For a local audience, caching and optimized images usually pay off more at first.

Should I lazy-load every image?

No. Use loading="lazy" on images below the fold, but let the main image at the top load normally, or your LCP gets worse.

Next articleWebsite down? How to find out whyWebsite down? Find out whether DNS, the certificate, the server or your code is to blame by reading the exact error and following a fixed diagnostic order.

More in Websites

See all 20 articles