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
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.
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:
- Modern format. AVIF and WebP are smaller than JPEG and PNG at the same visual quality. Offer both with a fallback.
- Responsive sizes. Do not send a 2000 px image to a phone that is 400 px wide.
- Declared dimensions.
widthandheightreserve the space and prevent CLS. - Lazy loading only below the fold.
<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:
<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
deferon 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:
Cache-Control: max-age=31536000, immutableThe HTML, which references those files, should always be revalidated:
Cache-Control: no-cacheCareful: 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?#
- Reload the page with DevTools open on the Network tab. On the second load, hashed files should show as "(memory cache)" or "(disk cache)".
- Check a file's headers:
Cache-ControlandContent-Encodingshould be present. - Run Lighthouse again and compare LCP, INP and CLS with the numbers you wrote down.
- 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
widthandheight, which causes CLS. - Giving a long
max-ageto 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
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.
More in Websites
See all 20 articles- What is a static site (and how to host one)A static site is a set of ready-made HTML, CSS and JavaScript files served the same to every visitor. Learn how it works, when to use one and how to host it.
- How much does it cost to host a website?Hosting a website costs anywhere from nothing to a few dozen dollars a month. See what goes into the bill: hosting, domain, traffic and extras, with real limits.
- How much does static site hosting cost?Hosting a static site costs between zero and a few dozen dollars a month in most cases. See how traffic sets the price, with step-by-step math.
- How much does it cost to host a Next.js app?Hosting a Next.js app costs from zero with a static export to tens of dollars a month with a server. See the billing models, traffic math and hidden costs.