Back to Blog
4 min read

How We Cut Page Load Time by 40% with One Image Format Change

The Hero Image That Was Costing Us Speed

We were wrapping up the final UI polish on AustinsElite’s new frontend experience—yes, it’s Laravel 12 under the hood, not Next.js, despite the old label—and one thing kept nagging me: our homepage hero image, while gorgeous, was dragging down our Lighthouse scores. At 640KB as a high-quality JPEG, it was the largest asset on the page. The initial load felt sluggish, especially on mobile. We knew we had to act.

This wasn’t just about aesthetics. Slow loading impacts bounce rates, SEO, and user trust. With the Laravel app serving the frontend and assets, we had full control over how images were processed and delivered. So we asked: could we get the same visual quality at a fraction of the size? The answer turned out to be a resounding yes—and it only took one format change.

From JPEG to WebP: A Simple Swap With Big Returns

We decided to convert the hero image from JPEG to WebP. WebP consistently delivers better compression than JPEG, often with comparable or better visual fidelity. Google’s own data shows WebP can reduce file size by 25–35% on average; in our case, it was even better.

Here’s how we did it:

  1. Conversion: We used Squoosh.app (a free, open-source tool by Google) to compress the original JPEG. We experimented with quality settings and landed on "low"—which, despite the name, looked excellent on both desktop and mobile screens. The result? A 384KB WebP file. That’s a 40% reduction, just like that.

  2. Integration: Since the frontend is Laravel-driven with Blade templates (not React or Next.js), we didn’t have the Next.js Image component available. Instead, we used a simple <picture> element to serve WebP to supporting browsers and fall back to JPEG for older ones:

<picture>
  <source srcset="/images/hero.webp" type="image/webp">
  <img src="/images/hero.jpg" alt="Austin's Elite Service Team" />
</picture>

This ensured backward compatibility while letting modern browsers reap the performance benefits.

  1. Build Pipeline: We added a quick step to our asset pipeline using Laravel Vite to automatically generate WebP versions during the build process. A simple shell script wraps cwebp (part of Google’s WebP tools) and runs on any new image added to /public/images/src. Now, every image gets a WebP twin without manual work.

The Numbers Don’t Lie

We ran Lighthouse before and after the change—same device, same network conditions (4G throttling, 1x CPU slowdown). Here’s what we saw:

  • Before (JPEG only):

    • Largest Contentful Paint (LCP): 3.8s
    • Total Page Weight: 1.4MB
    • Lighthouse Performance Score: 62
  • After (WebP with fallback):

    • Largest Contentful Paint (LCP): 2.3s
    • Total Page Weight: 1.02MB
    • Lighthouse Performance Score: 89

A 40% improvement in LCP. A 27-point jump in performance score. And all from one image.

This wasn’t a framework-level optimization or a complex code-splitting refactor. It was a single asset change—executed quickly, verified immediately, and scaled easily.

Asset Hygiene Is Part of Developer Discipline

This win reminded me that performance isn’t just about code—it’s about assets, delivery, and attention to detail. Too often, we treat images as static afterthoughts, but they’re first-class citizens in the user experience.

Moving forward, we’ve made WebP conversion mandatory in our design-to-development handoff. Designers export assets in PNG or JPEG, and our build process automatically generates optimized WebP versions. We’re also exploring AVIF for future gains, though browser support isn’t quite universal yet.

The takeaway? Don’t overlook the low-hanging fruit. Sometimes the biggest performance wins come from the smallest changes. And if you’re working on a Laravel app (or any server-rendered stack), you don’t need a React framework to make smart, modern image decisions.

Optimize your assets. Automate the process. Measure the impact. Repeat.

Newer post

From In-Memory to Database: How We Made RR Bot’s Lobby System Persistent

Older post

From Click to Conversion: How We Engineered the Dropoff Button for Speed and Clarity