DEV Community

The AI producer
The AI producer

Posted on

20 Web Performance Tweaks That Cut My Page Load Time in Half (No Build Step Required)

We all know performance matters. Google says 53% of mobile users bounce if a page takes longer than 3 seconds. But most performance advice stops at "use a CDN" and "compress your images" — which is like telling someone who wants to lose weight to "eat less."

Here are 20 concrete tweaks I applied to a real project that cut load time from 4.8s to 2.1s on mobile 4G. None of them require a build step, a paid tool, or a PhD.

1. Add loading="lazy" to below-the-fold images

<img src="hero.jpg" alt="Hero" />
<img src="chart-3.png" alt="Q3 chart" loading="lazy" />
Enter fullscreen mode Exit fullscreen mode

Images are usually the heaviest asset. Lazy-loading everything below the fold means the browser only fetches them when the user scrolls near them. This is a one-attribute change that often saves 1–2 seconds on image-heavy pages.

2. Set explicit width and height on images

<img src="hero.jpg" width="800" height="600" alt="Hero" />
Enter fullscreen mode Exit fullscreen mode

Without dimensions, the browser can't reserve space, so it reflows the page every time an image loads. Each reflow is a layout thrash. Dimensions prevent cumulative layout shift (CLS) entirely.

3. Serve modern image formats with a fallback

<picture>
  <source srcset="hero.avif" type="image/avif" />
  <source srcset="hero.webp" type="image/webp" />
  <img src="hero.jpg" alt="Hero" width="800" height="600" />
</picture>
Enter fullscreen mode Exit fullscreen mode

AVIF is ~50% smaller than JPEG at equivalent quality. WebP is ~30% smaller. The <picture> element lets the browser pick the best format it supports. Safari now supports both.

4. Defer non-critical JavaScript

<script src="analytics.js" defer></script>
<script src="chat-widget.js" defer></script>
Enter fullscreen mode Exit fullscreen mode

defer downloads the script in parallel with HTML parsing but executes it only after the document is fully parsed. Your analytics, chat widgets, and cookie banners do not need to block rendering.

5. Preconnect to your key origins

<link rel="preconnect" href="https://cdn.example.com" crossorigin />
<link rel="preconnect" href="https://api.example.com" />
Enter fullscreen mode Exit fullscreen mode

preconnect tells the browser to open the TCP/TLS handshake early, so when the actual request happens, the connection is already warm. This saves 100–300ms per third-party domain.

6. Inline critical CSS, defer the rest

<style>
  /* Only the CSS needed for above-the-fold */
  body { margin: 0; font-family: system-ui; }
  .hero { min-height: 60vh; }
</style>
<link rel="preload" href="full.css" as="style" onload="this.rel='stylesheet'" />
Enter fullscreen mode Exit fullscreen mode

Inlining ~2KB of critical CSS eliminates the render-blocking request for the main stylesheet, so first paint happens immediately. The full stylesheet loads async after.

7. Use font-display: swap

@font-face {
  font-family: "MyFont";
  src: url("myfont.woff2") format("woff2");
  font-display: swap;
}
Enter fullscreen mode Exit fullscreen mode

Without swap, the browser hides text for up to 3 seconds while the custom font downloads — users see a blank screen. With swap, it shows the fallback font immediately, then swaps in the custom font when ready.

8. Subset your fonts

Most fonts include hundreds of glyphs for languages you don't use. Subsetting to just the Latin character set (and the specific weights you use) can shrink a 200KB font file to 30KB. Tools like fonttools or glyphhanger do this in one command.

9. Replace animated GIFs with video

A 2MB animated GIF becomes a 200KB MP4. Same visual, 90% smaller:

<video autoplay muted loop playsinline>
  <source src="demo.mp4" type="video/mp4" />
</video>
Enter fullscreen mode Exit fullscreen mode

10. Use srcset for responsive images

<img
  src="hero-800.jpg"
  srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px, 800px"
  alt="Hero"
/>
Enter fullscreen mode Exit fullscreen mode

Why send a 1200px image to a phone that renders it at 400px? srcset lets the browser pick the right resolution.

11. Self-host fonts instead of loading from Google Fonts CDN

<!-- Before: two render-blocking requests to fonts.googleapis.com -->
<!-- After: self-hosted, same domain, no extra DNS lookup -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
Enter fullscreen mode Exit fullscreen mode

Google Fonts adds a DNS lookup, a TCP connection, and a redirect chain. Self-hosting eliminates all three.

12. Remove unused CSS

If your page uses 10% of Bootstrap, you're shipping 90% dead CSS. Audit with Chrome DevTools → Coverage tab, then strip unused rules. A 200KB CSS file often shrinks to 20KB.

13. Use content-visibility: auto for long pages

.feed-section {
  content-visibility: auto;
  contain-intrinsic-size: 500px;
}
Enter fullscreen mode Exit fullscreen mode

This tells the browser to skip rendering, layout, and paint for off-screen sections entirely. On long list/feed pages, this can cut rendering time by 50%+.

14. Minify and compress (gzip/brotli)

Brotli typically compresses 15–20% smaller than gzip. Enable it on your server:

brotli on;
brotli_types text/css application/javascript application/json image/svg+xml;
Enter fullscreen mode Exit fullscreen mode

15. Cache aggressively with immutable

<link rel="stylesheet" href="style.8f3a2b.css" />
Enter fullscreen mode Exit fullscreen mode
# Cache-busted filenames → cache forever
location ~* \.(css|js|woff2|png|jpg)$ {
  expires 1y;
  add_header Cache-Control "public, immutable";
}
Enter fullscreen mode Exit fullscreen mode

Fingerprinted filenames mean repeat visits load from cache — zero network requests.

16. Reduce third-party scripts

Every third-party script (analytics, chat, ads, A/B testing) is a separate HTTP request, a separate connection, and potential render-blocking. Audit regularly. I removed 4 scripts I wasn't even using and saved 600ms.

17. Use HTTP/2 or HTTP/3 multiplexing

HTTP/2 lets the browser fetch multiple assets over a single connection in parallel. If your server supports it (most do now), ensure it's enabled. No code changes needed.

18. Prefetch the next likely page

<link rel="prefetch" href="/checkout" />
Enter fullscreen mode Exit fullscreen mode

If you know the user is about to navigate to a page (e.g., they're on the cart, heading to checkout), prefetch it during idle time. The navigation becomes instant.

19. Replace heavy icon libraries with inline SVG

Font Awesome via CDN = 60KB of fonts + CSS for icons you may use 12 of. Inline SVG icons are ~200 bytes each, need zero requests, and are perfectly crisp at any size.

20. Measure, don't guess

# Core Web Vitals from the terminal
npx unlighthouse --site https://yoursite.com
Enter fullscreen mode Exit fullscreen mode

Or use the built-in Lighthouse audit in Chrome DevTools (Audits tab). Target: LCP under 2.5s, CLS under 0.1, INP under 200ms.


The takeaway

You don't need a fancy framework or a paid CDN to get fast. Most wins come from:

  • Deferring what isn't critical (scripts, below-fold images, non-critical CSS)
  • Right-sizing what is critical (responsive images, modern formats, subsets)
  • Caching what doesn't change (immutable + fingerprinted filenames)

Start with loading="lazy", defer, and explicit image dimensions — that's 3 changes that take 5 minutes and typically save 1–2 seconds.

If you want a deeper reference, I put together a Frontend Performance Optimization checklist with 30 patterns (the full version of what I used above, plus network, render, and JavaScript-specific tweaks): Frontend Performance Optimization — 30 Patterns.

And if you build side projects, I run a collection of 68 free developer tools (no signup, all client-side) over at free-tools-hub — including a few performance utilities.

What's the one tweak that made the biggest difference on your project? I'm always collecting new ones.

Top comments (0)