From Slow to Instant: How I Made Bokkah.com Insanely Fast by Caching Images with a Service Worker

Blog

Posted by Nuno Marques on 2 Feb 2025

What if I told you that you could make your React app load images almost instantly with a single technique?

This isn't some theoretical trick—it’s exactly what I achieved on Bokkah.com.

The results?

Hundreds of images loaded in milliseconds
Significantly fewer network requests
A near-instant browsing experience

But here’s the kicker: This optimization isn't just about images.
It can extend to API calls, AI-generated content, and dynamic collections, making your entire app feel blazing fast.

Let’s deep dive into the power of service workers and how they transformed my app.


The Problem: Why Image Loading Is a Performance Killer

1. Every Image Request Adds Latency

Each time your app fetches an image from the server or a CDN, there's an inherent delay due to:

  • DNS lookup
  • TLS handshake
  • Server processing
  • Network round trip time
  • Image decoding

Even with an optimized CDN, these requests stack up, affecting performance.

2. Unnecessary Network Calls on Revisits

Browsers already cache assets, but:

  • The default cache policy is not aggressive enough.
  • If the cache is invalidated, the browser still re-fetches the image.
  • Users on slow networks or with limited bandwidth experience significant delays.

3. Core Web Vitals and User Perception

Slow-loading images hurt:

Even with lazy loading, these performance hits add up.
So, what’s the fix?
👉 A Service Worker caching all images!


The Solution: Service Worker + Image Caching

Instead of relying on default browser caching, I implemented a custom caching strategy using a Service Worker.

How It Works:

  1. Intercept every image request
  2. Check if the image is already cached
  3. If cached → Load instantly from storage
  4. If not cached → Fetch, store it, and serve

Here’s the Service Worker Code That Made It Happen

To implement this optimization, I added the following service worker inside my React app’s frontend/public/service-worker.js file:

self.addEventListener('fetch', (event) => {
    if (event.request.destination === 'image') { // Cache only images
        event.respondWith(
            caches.open('image-cache').then((cache) =>
                cache.match(event.request).then((cachedResponse) => {
                    return cachedResponse || fetch(event.request).then((networkResponse) => {
                        cache.put(event.request, networkResponse.clone());
                        return networkResponse;
                    });
                })
            )
        );
    }
});

Implementing It in React

Once the Service Worker was created, I registered it in my index.tsx:

// Register the service worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js') // This file should be inside the `public/` folder
      .then((registration) => {
        console.log('Service Worker registered with scope:', registration.scope);
      })
      .catch((error) => {
        console.error('Service Worker registration failed:', error);
      });
  });
}

Why This Is a Game-Changer for Performance

The Before and After Results:

Before → Each image was fetched from the network every time
After → Cached images load instantly with zero network latency

Here’s what happened in the network tab after implementing this:

  • Hundreds of images loaded in under 30ms
  • (ServiceWorker) served images from cache instead of the network
  • Reduced total network requests, making my Bokkah App feel near-instant

Extending This Technique Beyond Images

While caching images dramatically improves load times, this technique isn’t limited to static assets. If your app relies on AI-generated content, dynamic collections, and frequent API calls, these too can benefit from caching strategies.

By extending service worker caching to API responses and AI-generated content, you can:

Reduce redundant OpenAI API calls → Faster content generation & lower costs
Cache user collections & data → Instant access without reloading
Optimize dynamic content → Minimize unnecessary database queries

This approach transforms not just images, but your entire app into a faster, more efficient experience.

Further Reading and References

To deepen your understanding of service workers and caching strategies, check out these resources:


Final Thoughts: Why You Should Implement This ASAP

With just a few lines of JavaScript, I made my React app insanely fast.
The Service Worker strategy:
Reduced image load times from seconds to milliseconds
Cut down network requests significantly
Created a near-instant browsing experience

But this is just the beginning.
If you're building a web app with dynamic content, AI-powered features, or social sharing, caching isn't optional—it's a must.


Key Takeaways:

  • Use service workers to cache images for instant load times.
  • Expand caching to API responses to reduce costs & latency.
  • Make AI-generated recipes & collections available offline.
  • Improve Core Web Vitals (LCP, FCP, TBT) for better SEO.

Have you tried using service workers in your app?