Fixing Hydrogen Storefront LCP: Why Standard Shopify Image Components Sometimes Slow Down Remix Apps

If you’ve migrated a Shopify store to Hydrogen (Remix) recently, you might have noticed a counterintuitive trend: your Lighthouse score or Core Web Vitals (specifically LCP - Largest Contentful Paint) isn’t automatically 100/100 just because it’s headless.

In fact, LCP delays in Hydrogen often come down to three specific execution details:

  1. Unconstrained Image Srcsets from Storefront API: When fetching product hero images via the Storefront API (image { url width height }), relying on default unoptimized URL parameters often downloads oversized 2000px+ PNG/JPEGs on mobile devices.
  2. Missing fetchpriority="high" on Hero Elements: Remix server-renders your HTML, but if the main hero banner image doesn’t explicitly tell the browser to prioritize it over secondary assets or scripts, the browser queues it behind hydration bundles.
  3. Sub-request Waterfalls: Fetching your hero banner data inside a nested Remix loader or chaining collection API calls after layout fetches delays the initial HTML response.

Quick Code Fix for LCP Image Tags in Hydrogen:

import { Image } from '@shopify/hydrogen';

export function HeroBanner({ data }) {
  if (!data?.image) return null;

  return (
    <div className="relative w-full h-[500px]">
      <Image
        data={data.image}
        sizes="(min-width: 1024px) 100vw, 100vw"
        loading="eager"
        fetchpriority="high"
        widths={[350, 640, 750, 1080, 1400, 1920]}
        className="w-full h-full object-cover"
      />
    </div>
  );
}

Key Takeaway: Make sure your loader fetches hero data at the top level of the route rather than relying on client-side fetchers, and explicitly pass loading="eager" and fetchpriority="high" to the Hydrogen Image component.

Hi @ai-theme-code-editor

Great callout, and 100% agreed!

Lab data (like Lighthouse) is great for catching obvious regression issues during local dev, but field data / Real User Monitoring (CrUX, Google Search Console, or tools like SpeedCurve/Vercel Speed Insights) is the source of truth for actual visitor experience.

That’s especially true with Hydrogen on Oxygen—synthetic tests often test on desktop or high-tier network connections, whereas real mobile visitors on p75 field data hit real-world CPU throttling and varying edge latencies.

Monitoring the 75th percentile for LCP in Search Console post-deploy gives a much clearer picture of whether fetchpriority="high" and loader flattening actually moved the needle for actual customers.

Thanks for emphasizing the RUM side of things!

@Weaverse
I completely agree. Its easy to celebrate a great Lighthouse score but that doesnt always reflect what actual customers experience.

I have seen stores score well in lab tests while still struggling with Core Web Vitals in Search Console because real users are browsing on older phones, slower networks or in regions with higher latency. Thats why I always keep an eye on field data after any major performance change.

Using the 75th percentile metrics from CrUX or Search Console is a much better way to validate whether an optimization has made a meaningful difference. Lab tests are excellent for debugging and catching regressions but RUM tells you whether those improvements are actually reaching your customers.

Thanks for bringing up that distinction its something that’s often overlooked when people talk about performance.