From Eager Loading to Image Preloading (Real Experiments):
This article is part of my Shopify Performance Engineering Series.
In my previous article - How I Improved a Shopify Store’s Performance from 30% to 62% - I explained the overall optimization journey.
One of the biggest contributors to that improvement was LCP.
In this post, we’ll go deeper into one of the most critical metrics: Largest Contentful Paint (LCP).
In this post, I’ll go deeper into how I optimized LCP through multiple experiments including what worked, what didn’t, and what actually made a measurable difference.
What is LCP (and why it matters)
Largest Contentful Paint (LCP) measures how long it takes for the main visible element on a page to load.
In most Shopify stores, this is usually:
hero banner image
featured product image
large above-the-fold section
If LCP is slow, users perceive the site as slow even if everything else loads fast.
Identifying the LCP Element:
Using Lighthouse and Chrome DevTools, I identified that:
👉 The LCP element on the homepage was the hero banner image
The issue was not the image size alone.
The real problem was:
The browser was discovering the image too late
Experiment 1: Default Behavior (Baseline)
Initially, the image was loaded normally with:
lazy loading in some cases
no priority hints
Result:
LCP was delayed
performance score ~30%
Experiment 2: Forcing Eager Loading
First improvement:
<img loading="eager">
Why this helps?
prevents lazy loading
ensures browser loads image immediately
Result:
slight LCP improvement
but still not optimal
👉 Problem: browser still needs to discover the image in DOM first
Experiment 3: Increasing Fetch Priority
Next, I used:
<img fetchpriority="high">
What this does?
signals browser: “this is important”
increases network priority
Result:
better LCP than eager loading alone
but still limited improvement
👉 Problem: request still starts after DOM parsing
Experiment 4: Image Preloading
To push further, I experimented with:
<link rel="preload" as="image" href="hero-image.jpg">
Why preload is powerful?
request starts in <head>
browser doesn’t wait for DOM
image loads earlier than render
Result:
significant improvement
performance increased to ~42–45%
In Shopify, images are often rendered like:
<img srcset="...">
This means:
browser chooses image size dynamically
exact URL is not fixed at build time
👉 Problem:
Preloading requires a specific image URL
Solution: Static Image Exposure
To solve this, I:
created a theme setting for hero image
exposed the image URL in <head>
used that for preloading
This allowed:
early fetch
correct resource prioritization
Experiment 5: Wrong Preload Size (Important Lesson)
Initially, I preloaded a large image (desktop size) for all devices.
This caused:
unnecessary data usage on mobile
slower load on weaker networks
👉 Lesson:
Preloading the wrong image can hurt performance
Final Optimization: Conditional Preloading
I implemented:
1280px image for desktop
375px image for mobile
This ensured:
correct image is loaded early
no unnecessary preload
Role of srcset and sizes:
To further optimize:
used proper srcset
defined accurate sizes
Example concept:
<img
srcset="image-375.jpg 375w, image-768.jpg 768w, image-1280.jpg 1280w"
sizes="(max-width: 768px) 100vw, 1280px"
>
This allows:
browser to choose optimal image
reduced network load
Important Insight
LCP optimization is not just about:
❌ making images smaller
❌ using lazy loading
It is about:
Making the browser discover and prioritize the image earlier
Common Mistakes in Shopify LCP Optimization:
Lazy loading LCP image
Never lazy load above-the-fold images.Missing fetch priority
Without priority hints, browser delays important resources.No preloading
Browser discovers image too late.Incorrect image sizes
Loading large images on mobile increases load time.
Final Results
After combining:
eager loading
fetchpriority
image preloading
correct sizing
LCP improved significantly and contributed heavily to:
30% → 62% performance improvement
Key Takeaways
If you're optimizing LCP in Shopify:
• identify the correct LCP element
• avoid lazy loading above-the-fold images
• use fetchpriority="high"
• preload critical images
• ensure correct image sizes
• use proper srcset and sizes
Final Thought:
LCP optimization is not about tricks.
It’s about understanding:
when the browser discovers the most important content
The earlier it discovers it, the faster your page feels.
Question for Developers
What has been your biggest challenge in optimizing LCP?
Have you tried preloading images in Shopify themes?
Top comments (2)
Great breakdown of the progressive experiments — the bit about preloading the wrong image size being counterproductive is often skipped over but it matters a lot on mobile.
One thing that pairs well with this LCP work: once you've nailed first-load performance, the next win is eliminating perceived delay on subsequent navigations. The Speculation Rules API lets the browser prerender likely next pages while the user is still on the current one — so clicking a product or collection link feels nearly instant.
I built a Shopify app called Prefetch (apps.shopify.com/prefetch) that injects speculation rules into theme layouts automatically, no code needed. The combination of solid LCP on first load + prerendering on navigation creates a consistently fast feel across the whole browsing session.
(Disclosure: I'm the developer)
What LCP score did you land on after all the optimizations? Curious what the ceiling looks like for a well-tuned Shopify store.
The preload size issue was a surprisingly important lesson, especially for mobile.
The Speculation Rules API is definitely interesting. I agree that once first-load performance is optimized, the next bottleneck is perceived delay during navigation.
In my case, I focused mainly on improving initial load metrics like LCP and TBT, but prerendering for collection -> product transitions sounds like a strong next step to explore.
Also interesting to see this being integrated at the app level, that makes adoption much easier in Shopify ecosystems.
After all optimizations, LCP landed roughly in the ~1.7s–2.3s range (shopify analytics) depending on device and network conditions. Still some room for improvement, but a significant jump from the baseline.
Appreciate you sharing this!