<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: GIRIDHAR DEV</title>
    <description>The latest articles on DEV Community by GIRIDHAR DEV (@giridhar_dev).</description>
    <link>https://dev.to/giridhar_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3817259%2F011052ff-3cbb-4f3a-a7f1-5d284f3b2ce4.png</url>
      <title>DEV Community: GIRIDHAR DEV</title>
      <link>https://dev.to/giridhar_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/giridhar_dev"/>
    <language>en</language>
    <item>
      <title>Modern CSS &amp; Rendering Performance in Shopify</title>
      <dc:creator>GIRIDHAR DEV</dc:creator>
      <pubDate>Sun, 29 Mar 2026 14:25:08 +0000</pubDate>
      <link>https://dev.to/giridhar_dev/modern-css-rendering-performance-in-shopify-559g</link>
      <guid>https://dev.to/giridhar_dev/modern-css-rendering-performance-in-shopify-559g</guid>
      <description>&lt;p&gt;&lt;strong&gt;What Actually Improves Rendering (and What Doesn’t)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is part of my Shopify Performance Engineering Series.&lt;/p&gt;

&lt;p&gt;In previous articles, I covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/giridhar_dev/how-i-improved-a-shopify-stores-performance-from-30-to-65-gtmetrix-5h97"&gt;Improving performance from 30% → 62%&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/giridhar_dev/optimizing-largest-contentful-paint-lcp-in-shopify-57cb"&gt;Optimizing LCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/giridhar_dev/how-third-party-apps-slow-down-shopify-stores-pmd"&gt;Reducing TBT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, I’ll focus on something deeper:&lt;/p&gt;

&lt;p&gt;👉 Rendering performance — what the browser actually does after loading resources&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Rendering Performance Matters?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;images are optimized&lt;/li&gt;
&lt;li&gt;JavaScript is deferred&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;your site can still feel slow because of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout calculations&lt;/li&gt;
&lt;li&gt;style recalculations&lt;/li&gt;
&lt;li&gt;paint work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browsers don’t just “load” pages — they:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;parse HTML&lt;/li&gt;
&lt;li&gt;build DOM&lt;/li&gt;
&lt;li&gt;calculate styles&lt;/li&gt;
&lt;li&gt;calculate layout&lt;/li&gt;
&lt;li&gt;paint pixels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Performance issues often come from steps 3–5, not just network.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ever wondered if we could improve page performance using CSS?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The Biggest Misconception&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most developers think:&lt;/p&gt;

&lt;p&gt;“If content is below the fold, it doesn’t affect performance”&lt;/p&gt;

&lt;p&gt;❌ This is wrong.&lt;/p&gt;

&lt;p&gt;By default, browsers still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calculate layout&lt;/li&gt;
&lt;li&gt;compute styles&lt;/li&gt;
&lt;li&gt;sometimes paint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So, for off-screen content use:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;content-visibility — What It Actually Does?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;content-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the browser:&lt;/p&gt;

&lt;p&gt;“&lt;strong&gt;Skip rendering work&lt;/strong&gt; for this subtree until it is needed”&lt;/p&gt;

&lt;p&gt;Specifically, the browser can skip:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout&lt;/li&gt;
&lt;li&gt;style calculation&lt;/li&gt;
&lt;li&gt;painting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real Impact (Accurate)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When used correctly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reduces initial rendering work&lt;/li&gt;
&lt;li&gt;improves interaction readiness&lt;/li&gt;
&lt;li&gt;improves metrics like INP and sometimes LCP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In some cases, rendering work can drop significantly (even multiple times faster)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When content-visibility Works Well&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use it when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content is below-the-fold&lt;/li&gt;
&lt;li&gt;sections are independent (no layout dependency)&lt;/li&gt;
&lt;li&gt;large DOM trees exist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;content affects layout above&lt;/li&gt;
&lt;li&gt;you rely heavily on DOM measurements (important!)&lt;/li&gt;
&lt;li&gt;The Hidden Problem: Layout Shift (CLS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you apply:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;content-visibility: auto;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The browser may treat the element as:&lt;/p&gt;

&lt;p&gt;👉 having no intrinsic size initially&lt;/p&gt;

&lt;p&gt;This can cause layout jumps.&lt;/p&gt;

&lt;p&gt;Correct Fix: contain-intrinsic-size&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;content-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;contain-intrinsic-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="m"&gt;500px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;provides a placeholder size&lt;/li&gt;
&lt;li&gt;prevents layout shifts&lt;/li&gt;
&lt;li&gt;stabilizes rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Without this, CLS issues are very likely&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Correction: content-visibility is NOT free&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you use APIs like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getBoundingClientRect()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offsetWidth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scrollHeight&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;on those elements:&lt;/p&gt;

&lt;p&gt;👉 browser is forced to render them anyway&lt;/p&gt;

&lt;p&gt;So you lose the benefit.&lt;/p&gt;

&lt;p&gt;This is explicitly warned in browser docs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forced Reflow — What Actually Happens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Forced reflow happens when JS asks:&lt;/p&gt;

&lt;p&gt;“Give me layout info NOW”&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;element.offsetWidth&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;element.offsetHeight&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;element.getBoundingClientRect()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 All of these can trigger layout calculation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what should you do?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Don’t avoid APIs blindly&lt;/li&gt;
&lt;li&gt;✅ Avoid calling them frequently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Better Strategy (Real Answer)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;batch DOM reads&lt;/li&gt;
&lt;li&gt;batch DOM writes&lt;/li&gt;
&lt;li&gt;avoid interleaving them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ResizeObserver — Is it better?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Yes, but with context.&lt;/p&gt;

&lt;p&gt;ResizeObserver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reacts to size changes asynchronously&lt;/li&gt;
&lt;li&gt;avoids manual polling&lt;/li&gt;
&lt;li&gt;reduces forced synchronous layout reads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BUT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ It still depends on layout updates happening&lt;/li&gt;
&lt;li&gt;⚠️ Overusing observers can also hurt performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;IntersectionObserver — When it helps?&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is genuinely useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lazy loading&lt;/li&gt;
&lt;li&gt;triggering work only when visible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Works very well with content-visibility&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS Optimization — What Actually Matters?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) Deep selectors (real impact)&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="nc"&gt;.wrapper&lt;/span&gt; &lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="nc"&gt;.text&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why bad:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;increases selector matching cost&lt;/li&gt;
&lt;li&gt;harder for browser to resolve&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) DOM depth (real impact)&lt;/p&gt;

&lt;p&gt;Deep DOM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;span&amp;gt;&lt;/span&gt;Text&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This increases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout complexity&lt;/li&gt;
&lt;li&gt;style recalculation cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) CSS modularization (real benefit)&lt;/p&gt;

&lt;p&gt;Separating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout styles&lt;/li&gt;
&lt;li&gt;animation styles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reduce layout recalculation&lt;/li&gt;
&lt;li&gt;improve maintainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Actually Improves Rendering Performance?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Based on real browser behavior:&lt;/p&gt;

&lt;p&gt;✅ High impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reducing DOM size&lt;/li&gt;
&lt;li&gt;using content-visibility correctly&lt;/li&gt;
&lt;li&gt;avoiding unnecessary layout calculations&lt;/li&gt;
&lt;li&gt;deferring off-screen rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Medium impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSS selector optimization&lt;/li&gt;
&lt;li&gt;modular CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ Low / misunderstood impact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blindly replacing offsetWidth&lt;/li&gt;
&lt;li&gt;assuming one API is “faster” than another&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Insight&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rendering performance is not about:&lt;/p&gt;

&lt;p&gt;❌ using specific APIs&lt;br&gt;
❌ micro-optimizing CSS&lt;/p&gt;

&lt;p&gt;It is about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reducing how much work the browser needs to do&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The biggest performance gains come from skipping work — not optimizing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Question for Developers&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have you used content-visibility in production?&lt;/li&gt;
&lt;li&gt;Did you face issues with layout shifts or unexpected rendering?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What’s Next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the next article, I’ll share:&lt;/p&gt;

&lt;p&gt;👉 Performance-first Shopify development rules I follow while building themes&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>css</category>
      <category>shopify</category>
    </item>
    <item>
      <title>How Third-Party Apps Slow Down Shopify Stores</title>
      <dc:creator>GIRIDHAR DEV</dc:creator>
      <pubDate>Sun, 29 Mar 2026 13:51:18 +0000</pubDate>
      <link>https://dev.to/giridhar_dev/how-third-party-apps-slow-down-shopify-stores-pmd</link>
      <guid>https://dev.to/giridhar_dev/how-third-party-apps-slow-down-shopify-stores-pmd</guid>
      <description>&lt;h2&gt;
  
  
  How Third-Party Apps Slow Down Shopify Stores
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Reducing 1000ms of Total Blocking Time (TBT)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is part of my Shopify Performance Engineering Series.&lt;/p&gt;

&lt;p&gt;In my previous articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/giridhar_dev/how-i-improved-a-shopify-stores-performance-from-30-to-65-gtmetrix-5h97"&gt;How I Improved a Shopify Store’s Performance from 30% to 65%&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/giridhar_dev/optimizing-largest-contentful-paint-lcp-in-shopify-57cb"&gt;Optimizing Largest Contentful Paint in Shopify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I covered the overall optimization journey and LCP improvements.&lt;/p&gt;

&lt;p&gt;In this post, we’ll focus on another critical metric:&lt;/p&gt;

&lt;p&gt;👉 Total Blocking Time (TBT)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Total Blocking Time (TBT)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Total Blocking Time measures how long the browser’s main thread is blocked by JavaScript.&lt;/p&gt;

&lt;p&gt;When the main thread is blocked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user interactions are delayed&lt;/li&gt;
&lt;li&gt;scrolling becomes janky&lt;/li&gt;
&lt;li&gt;clicks feel unresponsive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if the page looks loaded, it doesn’t feel fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identifying the Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While analyzing performance using Lighthouse and DevTools, I noticed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;high Total Blocking Time&lt;/li&gt;
&lt;li&gt;long JavaScript execution tasks&lt;/li&gt;
&lt;li&gt;delayed interactivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, I suspected Google Tag Manager (GTM).&lt;/p&gt;

&lt;p&gt;But after deeper investigation, I found the real bottleneck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Real Bottleneck: Third-Party Apps&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One Shopify app was responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loading a 4MB font file&lt;/li&gt;
&lt;li&gt;injecting heavy JavaScript&lt;/li&gt;
&lt;li&gt;triggering multiple network requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;homepage size reached ~11MB&lt;/li&gt;
&lt;li&gt;TBT increased by ~1000ms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Third-Party Apps Are Problematic?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most Shopify apps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inject scripts globally&lt;/li&gt;
&lt;li&gt;run on every page&lt;/li&gt;
&lt;li&gt;execute during initial load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;main thread blocking&lt;/li&gt;
&lt;li&gt;delayed rendering&lt;/li&gt;
&lt;li&gt;unnecessary work for the browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Investigation Using DevTools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using the Performance tab in Chrome DevTools, I observed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;long tasks (&amp;gt;50ms)&lt;/li&gt;
&lt;li&gt;script execution blocking rendering&lt;/li&gt;
&lt;li&gt;heavy main-thread activity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 The app scripts were clearly dominating execution time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Attempt: Let It Load Normally&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initially, the app was loading during page initialization.&lt;/p&gt;

&lt;p&gt;This caused:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blocking during critical rendering phase&lt;/li&gt;
&lt;li&gt;increased TBT&lt;/li&gt;
&lt;li&gt;slower interactivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Solution: Interaction-Based Loading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of loading the app immediately, I changed the strategy.&lt;/p&gt;

&lt;p&gt;👉 Load the app only when the user clicks the help icon&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.help-icon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;loadSupportIframe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no app scripts during initial load&lt;/li&gt;
&lt;li&gt;no unnecessary blocking&lt;/li&gt;
&lt;li&gt;better main-thread availability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why This Works?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;Load everything → then render page&lt;br&gt;
We do:&lt;br&gt;
Render page → load features when needed&lt;/p&gt;

&lt;p&gt;This reduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total Blocking Time&lt;/li&gt;
&lt;li&gt;network congestion&lt;/li&gt;
&lt;li&gt;CPU workload&lt;/li&gt;
&lt;li&gt;Result After Optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After applying interaction-based loading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TBT reduced significantly&lt;/li&gt;
&lt;li&gt;performance score improved&lt;/li&gt;
&lt;li&gt;page became more responsive&lt;/li&gt;
&lt;li&gt;Additional Improvements for TBT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beyond third-party apps, I implemented several optimizations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Deferring Non-Critical JavaScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Scripts that were not required immediately were deferred.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;defer&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents blocking during HTML parsing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Moving Scripts After Page Load&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some scripts were moved to run after:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;load&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;loadNonCriticalScripts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;critical rendering is not blocked&lt;/li&gt;
&lt;li&gt;scripts run only after page is usable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Splitting Large JavaScript Files&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of loading one large file I:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;broke scripts into smaller modules&lt;/li&gt;
&lt;li&gt;loaded only what was needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;execution time&lt;/li&gt;
&lt;li&gt;blocking duration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Removing Unused App Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When apps were removed, I ensured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;leftover JS was deleted&lt;/li&gt;
&lt;li&gt;unused CSS was removed&lt;/li&gt;
&lt;li&gt;Liquid code was cleaned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduced unnecessary execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Avoiding Heavy Inline Scripts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Large inline scripts were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;moved out of &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;placed near the end of &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduced blocking during initial render.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Insight&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TBT optimization is not about writing faster code.&lt;br&gt;
It is about:&lt;br&gt;
reducing the amount of JavaScript that runs during page load, especially large bundles that create long tasks (&amp;gt;50ms) and block the main thread.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Common Mistakes in Shopify TBT Optimization:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Loading all apps on every page&lt;br&gt;
Many apps are not needed globally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running scripts too early&lt;br&gt;
Non-critical scripts should not run during initial render.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keeping unused app code&lt;br&gt;
Uninstalled apps often leave scripts behind.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Large JavaScript bundles&lt;br&gt;
Big files increase execution time and blocking.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Real-World Impact&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After reducing TBT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;page felt more responsive&lt;/li&gt;
&lt;li&gt;interactions became smoother&lt;/li&gt;
&lt;li&gt;perceived performance improved&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even without changing visual load speed, the site felt significantly faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're optimizing TBT in Shopify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reduce third-party scripts&lt;/li&gt;
&lt;li&gt;load apps only when needed&lt;/li&gt;
&lt;li&gt;defer non-critical JavaScript&lt;/li&gt;
&lt;li&gt;split large JS files&lt;/li&gt;
&lt;li&gt;remove unused code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most improvements come from:&lt;br&gt;
removing unnecessary work rather than optimizing existing code&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Performance is not just about how fast a page loads.&lt;br&gt;
It’s about how quickly a user can interact with it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Question for Developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you faced performance issues due to third-party scripts?&lt;br&gt;
What strategies have worked best for you in reducing TBT?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s Next&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the next article, I’ll explore:&lt;/p&gt;

&lt;p&gt;👉 Modern CSS techniques like content-visibility and how they improve rendering performance&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>shopify</category>
    </item>
    <item>
      <title>Optimizing Largest Contentful Paint (LCP) in Shopify</title>
      <dc:creator>GIRIDHAR DEV</dc:creator>
      <pubDate>Sun, 29 Mar 2026 13:17:06 +0000</pubDate>
      <link>https://dev.to/giridhar_dev/optimizing-largest-contentful-paint-lcp-in-shopify-57cb</link>
      <guid>https://dev.to/giridhar_dev/optimizing-largest-contentful-paint-lcp-in-shopify-57cb</guid>
      <description>&lt;p&gt;&lt;strong&gt;From Eager Loading to Image Preloading (Real Experiments):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is part of my Shopify Performance Engineering Series.&lt;/p&gt;

&lt;p&gt;In my previous article - &lt;a href="https://dev.to/giridhar_dev/how-i-improved-a-shopify-stores-performance-from-30-to-65-gtmetrix-5h97"&gt;How I Improved a Shopify Store’s Performance from 30% to 62%&lt;/a&gt; - I explained the overall optimization journey.&lt;/p&gt;

&lt;p&gt;One of the biggest contributors to that improvement was LCP.&lt;/p&gt;

&lt;p&gt;In this post, we’ll go deeper into one of the most critical metrics: Largest Contentful Paint (LCP).&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is LCP&lt;/strong&gt; (and why it matters)&lt;/p&gt;

&lt;p&gt;Largest Contentful Paint (LCP) measures how long it takes for the main visible element on a page to load.&lt;/p&gt;

&lt;p&gt;In most Shopify stores, this is usually:&lt;/p&gt;

&lt;p&gt;hero banner image&lt;br&gt;
featured product image&lt;br&gt;
large above-the-fold section&lt;/p&gt;

&lt;p&gt;If LCP is slow, users perceive the site as slow even if everything else loads fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identifying the LCP Element:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using Lighthouse and Chrome DevTools, I identified that:&lt;/p&gt;

&lt;p&gt;👉 The LCP element on the homepage was the hero banner image&lt;/p&gt;

&lt;p&gt;The issue was not the image size alone.&lt;/p&gt;

&lt;p&gt;The real problem was:&lt;/p&gt;

&lt;p&gt;The browser was discovering the image too late&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 1: Default Behavior (Baseline)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initially, the image was loaded normally with:&lt;br&gt;
lazy loading in some cases&lt;br&gt;
no priority hints&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
LCP was delayed&lt;br&gt;
performance score ~30%&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 2: Forcing Eager Loading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First improvement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"eager"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this helps?&lt;br&gt;
prevents lazy loading&lt;br&gt;
ensures browser loads image immediately&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
slight LCP improvement&lt;br&gt;
but still not optimal&lt;/p&gt;

&lt;p&gt;👉 Problem: browser still needs to discover the image in DOM first&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 3: Increasing Fetch Priority&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;fetchpriority=&lt;/span&gt;&lt;span class="s"&gt;"high"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does?&lt;br&gt;
signals browser: “this is important”&lt;br&gt;
increases network priority&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
better LCP than eager loading alone&lt;br&gt;
but still limited improvement&lt;/p&gt;

&lt;p&gt;👉 Problem: request still starts after DOM parsing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 4: Image Preloading&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To push further, I experimented with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt; &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"image"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"hero-image.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why preload is powerful?&lt;br&gt;
request starts in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;&lt;br&gt;
browser doesn’t wait for DOM&lt;br&gt;
image loads earlier than render&lt;/p&gt;

&lt;p&gt;Result:&lt;br&gt;
significant improvement&lt;br&gt;
performance increased to ~42–45%&lt;/p&gt;

&lt;p&gt;In Shopify, images are often rendered like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;br&gt;
browser chooses image size dynamically&lt;br&gt;
exact URL is not fixed at build time&lt;/p&gt;

&lt;p&gt;👉 Problem:&lt;/p&gt;

&lt;p&gt;Preloading requires a specific image URL&lt;/p&gt;

&lt;p&gt;Solution: Static Image Exposure&lt;/p&gt;

&lt;p&gt;To solve this, I:&lt;br&gt;
created a theme setting for hero image&lt;br&gt;
exposed the image URL in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;&lt;br&gt;
used that for preloading&lt;/p&gt;

&lt;p&gt;This allowed:&lt;br&gt;
early fetch&lt;br&gt;
correct resource prioritization&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiment 5: Wrong Preload Size (Important Lesson)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initially, I preloaded a large image (desktop size) for all devices.&lt;/p&gt;

&lt;p&gt;This caused:&lt;br&gt;
unnecessary data usage on mobile&lt;br&gt;
slower load on weaker networks&lt;/p&gt;

&lt;p&gt;👉 Lesson:&lt;/p&gt;

&lt;p&gt;Preloading the wrong image can hurt performance&lt;/p&gt;

&lt;p&gt;Final Optimization: Conditional Preloading&lt;/p&gt;

&lt;p&gt;I implemented:&lt;br&gt;
1280px image for desktop&lt;br&gt;
375px image for mobile&lt;/p&gt;

&lt;p&gt;This ensured:&lt;br&gt;
correct image is loaded early&lt;br&gt;
no unnecessary preload&lt;/p&gt;

&lt;p&gt;Role of srcset and sizes:&lt;/p&gt;

&lt;p&gt;To further optimize:&lt;br&gt;
used proper srcset&lt;br&gt;
defined accurate sizes&lt;/p&gt;

&lt;p&gt;Example concept:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; 
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"image-375.jpg 375w, image-768.jpg 768w, image-1280.jpg 1280w"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 768px) 100vw, 1280px"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows:&lt;br&gt;
browser to choose optimal image&lt;br&gt;
reduced network load&lt;br&gt;
Important Insight&lt;/p&gt;

&lt;p&gt;LCP optimization is not just about:&lt;/p&gt;

&lt;p&gt;❌ making images smaller&lt;br&gt;
❌ using lazy loading&lt;/p&gt;

&lt;p&gt;It is about:&lt;/p&gt;

&lt;p&gt;Making the browser discover and prioritize the image earlier&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Mistakes in Shopify LCP Optimization:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Lazy loading LCP image&lt;br&gt;
Never lazy load above-the-fold images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Missing fetch priority&lt;br&gt;
Without priority hints, browser delays important resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No preloading&lt;br&gt;
Browser discovers image too late.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incorrect image sizes&lt;br&gt;
Loading large images on mobile increases load time.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Final Results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After combining:&lt;br&gt;
eager loading&lt;br&gt;
fetchpriority&lt;br&gt;
image preloading&lt;br&gt;
correct sizing&lt;/p&gt;

&lt;p&gt;LCP improved significantly and contributed heavily to:&lt;br&gt;
30% → 62% performance improvement&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're optimizing LCP in Shopify:&lt;/p&gt;

&lt;p&gt;• identify the correct LCP element&lt;br&gt;
• avoid lazy loading above-the-fold images&lt;br&gt;
• use &lt;code&gt;fetchpriority="high"&lt;/code&gt;&lt;br&gt;
• preload critical images&lt;br&gt;
• ensure correct image sizes&lt;br&gt;
• use proper srcset and sizes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thought:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LCP optimization is not about tricks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It’s about understanding:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;when the browser discovers the most important content&lt;br&gt;
The earlier it discovers it, the faster your page feels.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Question for Developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What has been your biggest challenge in optimizing LCP?&lt;br&gt;
Have you tried preloading images in Shopify themes?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>shopify</category>
    </item>
    <item>
      <title>How I Improved a Shopify Store’s Performance from 30% to 65% - GTmetrix</title>
      <dc:creator>GIRIDHAR DEV</dc:creator>
      <pubDate>Tue, 10 Mar 2026 17:26:26 +0000</pubDate>
      <link>https://dev.to/giridhar_dev/how-i-improved-a-shopify-stores-performance-from-30-to-65-gtmetrix-5h97</link>
      <guid>https://dev.to/giridhar_dev/how-i-improved-a-shopify-stores-performance-from-30-to-65-gtmetrix-5h97</guid>
      <description>&lt;p&gt;&lt;strong&gt;A Real Shopify Performance Optimization Journey&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we upgraded our Shopify store to a new theme, I expected the performance to improve automatically.&lt;/p&gt;

&lt;p&gt;Instead, the first performance test showed something alarming.&lt;/p&gt;

&lt;p&gt;The store scored only 30% on GTmetrix — exactly the same as the old theme.&lt;/p&gt;

&lt;p&gt;Despite migrating to a new theme, the website was still slow.&lt;/p&gt;

&lt;p&gt;That moment started a deep investigation into Shopify performance optimization, Core Web Vitals, third-party scripts, and browser rendering behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You'll Learn&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article I’ll cover:&lt;/p&gt;

&lt;p&gt;-&amp;gt; Investigating slow Shopify performance&lt;br&gt;
-&amp;gt; Optimizing Largest Contentful Paint (LCP)&lt;br&gt;
-&amp;gt; Reducing Total Blocking Time (TBT)&lt;br&gt;
-&amp;gt; Handling third-party scripts efficiently&lt;br&gt;
-&amp;gt; Fixing layout shifts (CLS)&lt;/p&gt;

&lt;p&gt;Over several weeks of experimentation, debugging, and testing, the store’s performance improved from 30% to 62%.&lt;/p&gt;

&lt;p&gt;This article documents that journey.&lt;/p&gt;

&lt;p&gt;Understanding the Performance Problem&lt;/p&gt;

&lt;p&gt;Modern website performance is heavily influenced by Core Web Vitals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Page Load:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;-&amp;gt; LCP (Largest Contentful Paint) - When the main visible content appears&lt;br&gt;
-&amp;gt; TBT (Total Blocking Time) - How long the main thread is blocked by JavaScript&lt;br&gt;
-&amp;gt; CLS (Cumulative Layout Shift) - Unexpected layout movement during loading&lt;/p&gt;

&lt;p&gt;Improving &lt;strong&gt;Core Web Vitals&lt;/strong&gt; in Shopify themes requires optimizing several aspects of a page:&lt;/p&gt;

&lt;p&gt;-&amp;gt; images&lt;br&gt;
-&amp;gt; scripts&lt;br&gt;
-&amp;gt; rendering behavior&lt;br&gt;
-&amp;gt; third-party integrations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Initial Situation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was working on upgrading a Shopify store to a new Booster theme version.&lt;br&gt;
Migrating the theme and recreating all configurations from the live website took nearly a month.&lt;br&gt;
Once everything was configured — including several third-party apps — I assumed the new theme would perform better.&lt;/p&gt;

&lt;p&gt;However, the &lt;strong&gt;first GTmetrix test&lt;/strong&gt; told a different story.&lt;/p&gt;

&lt;p&gt;Metric  Result&lt;br&gt;
Performance Score   ~30%&lt;br&gt;
GTmetrix Grade  E–F&lt;/p&gt;

&lt;p&gt;This meant the theme upgrade alone had no meaningful performance impact.&lt;/p&gt;

&lt;p&gt;So the real question became:&lt;/p&gt;

&lt;p&gt;What exactly was slowing the store down?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1:&lt;/strong&gt; Investigating Largest Contentful Paint (LCP)&lt;/p&gt;

&lt;p&gt;The first major issue was Largest Contentful Paint.&lt;br&gt;
On the homepage, the LCP element was the hero banner image.&lt;br&gt;
The browser was discovering and loading this image too late during rendering.&lt;/p&gt;

&lt;p&gt;Experiment 1: Loading the image eagerly&lt;/p&gt;

&lt;p&gt;The first attempt was forcing the hero image to load eagerly.&lt;/p&gt;

&lt;p&gt;loading="eager"&lt;/p&gt;

&lt;p&gt;This ensured the browser prioritized loading the hero image earlier.&lt;br&gt;
The improvement was small but noticeable.&lt;/p&gt;

&lt;p&gt;Experiment 2: Increasing fetch priority&lt;/p&gt;

&lt;p&gt;Next, I experimented with:&lt;/p&gt;

&lt;p&gt;fetchpriority="high"&lt;/p&gt;

&lt;p&gt;This tells the browser that the image is a high-priority resource.&lt;br&gt;
The LCP improved slightly, but it was still slower than expected.&lt;/p&gt;

&lt;p&gt;Experiment 3: Image preloading&lt;/p&gt;

&lt;p&gt;To push optimization further, I experimented with preloading the hero image.&lt;/p&gt;

&lt;p&gt;However, Shopify dynamically generates image URLs using srcset, which makes preloading tricky.&lt;br&gt;
To work around this, I created a theme setting exposing the hero image URL, allowing it to be preloaded in the head tag. We cannot access section specific data (here - image banner section) in the head tag. So we need to create a global theme setting for this.&lt;br&gt;
This improved the performance score from 30% to around 42–45%.&lt;br&gt;
But performance optimization rarely stops with a single improvement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowylacbl8qglmq2mhq7j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fowylacbl8qglmq2mhq7j.jpg" alt="Image showing LCP improvement in Pagespeed report" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2:&lt;/strong&gt; Investigating Total Blocking Time (TBT)&lt;/p&gt;

&lt;p&gt;Next, I analyzed Total Blocking Time, which measures how long JavaScript blocks the browser’s main thread.&lt;br&gt;
Initially I suspected Google Tag Manager, since it loads multiple scripts.&lt;br&gt;
But deeper analysis revealed a bigger problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3:&lt;/strong&gt; Discovering the Real Bottleneck&lt;/p&gt;

&lt;p&gt;One third-party application was responsible for most of the slowdown.&lt;br&gt;
The app loaded:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a 4MB font file&lt;/li&gt;
&lt;li&gt;several large scripts&lt;/li&gt;
&lt;li&gt;heavy network requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, the homepage size had reached 11MB.&lt;br&gt;
Even worse, the scripts from this app caused nearly 1000ms of Total Blocking Time.&lt;/p&gt;

&lt;p&gt;The Solution: Interaction-Based Loading&lt;/p&gt;

&lt;p&gt;Instead of loading the app during page initialization, I changed the logic so the app loads only when the user clicks the help icon.&lt;/p&gt;

&lt;p&gt;This ensured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the heavy iframe is not loaded during page load&lt;/li&gt;
&lt;li&gt;unnecessary network requests are avoided&lt;/li&gt;
&lt;li&gt;javaScript execution does not block the main thread&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This small architectural change significantly improved performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 4:&lt;/strong&gt; Image Optimization&lt;/p&gt;

&lt;p&gt;While analyzing the network waterfall, I discovered another issue.&lt;br&gt;
Many images were loaded at 768px width, even on smaller mobile screens.&lt;br&gt;
By resizing images appropriately (for example 375px for mobile devices), I reduced the homepage image payload by 30–40%.&lt;/p&gt;

&lt;p&gt;This had two major benefits:&lt;/p&gt;

&lt;p&gt;• smaller page size and faster downloads&lt;br&gt;
• reduced JavaScript and rendering work, which also helped improve Total Blocking Time (TBT)&lt;/p&gt;

&lt;p&gt;Optimizing images not only improved LCP but also reduced the amount of work the browser had to perform during page load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 5:&lt;/strong&gt; Optimizing Collection and Product Pages&lt;/p&gt;

&lt;p&gt;I realized that optimizing only the homepage was not enough.&lt;br&gt;
Collection pages and product pages also needed improvements.&lt;br&gt;
On collection pages, the LCP element was usually one of the first product images.&lt;/p&gt;

&lt;p&gt;I optimized them by:&lt;/p&gt;

&lt;p&gt;-&amp;gt; preloading important images&lt;br&gt;
-&amp;gt; optimizing image sizes&lt;br&gt;
-&amp;gt; improving product card rendering&lt;/p&gt;

&lt;p&gt;The difference compared to the live theme was significant.&lt;/p&gt;

&lt;p&gt;Page    Live Theme  Optimized Theme&lt;br&gt;
Collection Page ~15%    ~70%&lt;/p&gt;

&lt;p&gt;For product pages, I applied a similar strategy by preloading the first product images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 6:&lt;/strong&gt; Avoiding Unnecessary Resource Loading&lt;/p&gt;

&lt;p&gt;Another issue I discovered was that some resources were loading on every page even when they were not needed.&lt;br&gt;
Using Shopify’s template.name, I implemented page-specific loading.&lt;br&gt;
This ensured resources load only on relevant pages, reducing unnecessary network requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 7:&lt;/strong&gt; Fixing Layout Shifts (CLS)&lt;/p&gt;

&lt;p&gt;Another Core Web Vital that required improvement was Cumulative Layout Shift.&lt;br&gt;
Layout shifts were caused by:&lt;/p&gt;

&lt;p&gt;-&amp;gt; late-loading fonts&lt;br&gt;
-&amp;gt; header dimension changes&lt;br&gt;
-&amp;gt; dynamic UI elements&lt;/p&gt;

&lt;p&gt;To fix this, I defined explicit layout dimensions so the browser reserves space before elements load.&lt;br&gt;
This stabilized the page layout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 8:&lt;/strong&gt; Rendering Optimization with Modern CSS&lt;/p&gt;

&lt;p&gt;To reduce rendering work for the browser, I used modern CSS techniques:&lt;/p&gt;

&lt;p&gt;content-visibility&lt;br&gt;
contain-intrinsic-size&lt;/p&gt;

&lt;p&gt;These allow the browser to skip rendering off-screen content until it becomes visible.&lt;br&gt;
This significantly reduced rendering cost for below-the-fold sections.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My Debugging Workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;During the investigation I relied on several tools.&lt;/p&gt;

&lt;p&gt;Lighthouse – local testing and layout debugging&lt;br&gt;
GTmetrix – network waterfall analysis&lt;br&gt;
WebPageTest – rendering insights&lt;br&gt;
Chrome DevTools – CPU throttling and performance profiling&lt;/p&gt;

&lt;p&gt;Testing under mobile CPU throttling and slow network conditions helped reveal issues that were not visible on powerful desktops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Small Shopify Performance Testing Trick:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While testing preview themes, I noticed performance results were slightly worse.&lt;br&gt;
This happens because the Shopify preview bar injects additional scripts.&lt;br&gt;
However, the preview bar can be disabled using the pb=0 query parameter.&lt;/p&gt;

&lt;p&gt;Example preview URL:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://example-store.myshopify.com/?preview_theme_id=123456789&amp;amp;pb=0" rel="noopener noreferrer"&gt;https://example-store.myshopify.com/?preview_theme_id=123456789&amp;amp;pb=0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without pb=0, Shopify injects the preview toolbar which can affect performance measurements.&lt;br&gt;
Adding this parameter allows more accurate testing of preview themes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Results&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After several rounds of optimization, the results improved significantly.&lt;/p&gt;

&lt;p&gt;Before: &lt;br&gt;
Performance Score  ~30%&lt;br&gt;
GTmetrix Grade  ~ E/F&lt;br&gt;
After:&lt;br&gt;
Performance Score  ~62%&lt;br&gt;
GTmetrix Grade  ~ C&lt;/p&gt;

&lt;p&gt;The improvement came from many small optimizations combined together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Performance Matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Website speed directly affects user behavior.&lt;br&gt;
Research shows that a 1-second delay in page load time can reduce conversions by around 7%.&lt;/p&gt;

&lt;p&gt;For e-commerce stores, performance directly impacts revenue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're optimizing a Shopify store, these steps usually provide the biggest improvements:&lt;/p&gt;

&lt;p&gt;• optimize LCP images&lt;br&gt;
• reduce third-party scripts&lt;br&gt;
• lazy load non-critical resources&lt;br&gt;
• optimize image sizes&lt;br&gt;
• stabilize layouts to prevent CLS&lt;/p&gt;

&lt;p&gt;Most performance gains come from removing unnecessary work rather than adding more code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This project taught me that performance optimization is not about chasing benchmark scores.&lt;/p&gt;

&lt;p&gt;It’s about understanding how browsers load and render pages, and eliminating everything that slows that process down.&lt;/p&gt;

&lt;p&gt;Performance optimization is not about making websites faster.&lt;br&gt;
It’s about removing everything that makes them slow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question for Developers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you faced similar performance challenges when working with Shopify or other frontend frameworks?&lt;/p&gt;

&lt;p&gt;What optimization had the biggest impact in your projects?&lt;/p&gt;

&lt;p&gt;This article is part of my Shopify Performance Engineering Series.&lt;/p&gt;

&lt;p&gt;In the next article, I’ll dive deeper into optimizing Largest Contentful Paint in Shopify through multiple experiments with eager loading, fetchpriority, and image preloading.&lt;/p&gt;

</description>
      <category>shopify</category>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
