DEV Community

Cover image for How I Fixed a Slow Shopify Product Page Without Rebuilding the Theme
Amaan Mirza
Amaan Mirza

Posted on

How I Fixed a Slow Shopify Product Page Without Rebuilding the Theme

A Shopify store can look beautiful and still feel slow.

One of the most common situations I've seen is a product page containing large images, multiple sections, third-party scripts, app blocks, and custom JavaScript.

The first reaction is often:

"We need a new theme."

But sometimes you don't need to rebuild the entire Shopify store.

You can get significant improvements by finding the actual bottleneck and fixing it at the theme level.

In this article, I'll walk through a practical example of improving a Shopify product page using Liquid, JavaScript, and better image loading techniques.

If you need help with Shopify theme customization, performance improvements, or custom development, you can also check out my Shopify development service:

Shopify Store Design & Development Service


The Problem

Imagine a Shopify product page like this:

Product Page
│
├── Large Hero Image
├── Product Gallery
├── Product Information
├── Reviews App
├── Recommendation App
├── Recently Viewed App
├── Custom Animation
├── Newsletter Popup
└── Chat Widget
Enter fullscreen mode Exit fullscreen mode

The page looks great.

But on mobile, customers experience:

  • Slow initial loading
  • Images appearing late
  • Layout shifting
  • Delayed interactions
  • Slow product gallery
  • Unnecessary JavaScript execution

The important question is:

Which part is actually causing the problem?


Step 1: Don't Guess — Measure First

Before changing code, check the page using tools such as:

  • Chrome DevTools
  • Lighthouse
  • PageSpeed Insights
  • Shopify's own analytics/performance information

Look for:

  • Large image files
  • Render-blocking resources
  • Long JavaScript tasks
  • Third-party scripts
  • Layout shifts
  • Slow network requests

For example, if your product hero image is 2500×2500 pixels but the customer is viewing it at 600×600 pixels, you're sending significantly more image data than necessary.

That's an easy place to start.


Step 2: Optimize Shopify Images

Shopify's image CDN can generate appropriately sized images.

Instead of simply outputting:

{{ product.featured_image | image_url }}
Enter fullscreen mode Exit fullscreen mode

you can request an appropriate width:

{{ product.featured_image | image_url: width: 800 }}
Enter fullscreen mode Exit fullscreen mode

Then use it inside an image element:

<img
  src="{{ product.featured_image | image_url: width: 800 }}"
  alt="{{ product.featured_image.alt | escape }}"
  width="800"
  height="800"
>
Enter fullscreen mode Exit fullscreen mode

This gives the browser a more appropriate resource instead of unnecessarily downloading a huge original image.


Step 3: Use Responsive Images

A better approach is to provide multiple image sizes.

<img
  src="{{ product.featured_image | image_url: width: 800 }}"
  srcset="
    {{ product.featured_image | image_url: width: 400 }} 400w,
    {{ product.featured_image | image_url: width: 800 }} 800w,
    {{ product.featured_image | image_url: width: 1200 }} 1200w
  "
  sizes="(max-width: 749px) 100vw, 800px"
  alt="{{ product.featured_image.alt | escape }}"
  width="1200"
  height="1200"
>
Enter fullscreen mode Exit fullscreen mode

Now the browser can choose an appropriate resource based on the device and available layout size.

This is especially useful for product galleries.


Step 4: Don't Lazy-Load the Main Product Image

Here's an important distinction.

You may want to lazy-load images that are below the fold.

But the main product image is often one of the first important visual elements on the page.

For the primary image, I generally avoid unnecessarily delaying its loading.

For example:

<img
  src="{{ product.featured_image | image_url: width: 1200 }}"
  alt="{{ product.featured_image.alt | escape }}"
  fetchpriority="high"
  width="1200"
  height="1200"
>
Enter fullscreen mode Exit fullscreen mode

For images further down the page, lazy loading can make more sense:

<img
  src="{{ image | image_url: width: 800 }}"
  loading="lazy"
  alt="{{ image.alt | escape }}"
  width="800"
  height="800"
>
Enter fullscreen mode Exit fullscreen mode

The idea isn't:

"Lazy-load everything."

The idea is:

"Load important content early and defer content that isn't immediately needed."


Step 5: Reduce Unnecessary JavaScript

Another common problem is loading JavaScript for functionality that the customer may never use.

For example, imagine a custom animation script:

document.querySelectorAll('.product-card').forEach(card => {
  // animation logic
});
Enter fullscreen mode Exit fullscreen mode

If your page contains hundreds of product elements, this can become unnecessarily expensive.

Instead, initialize functionality only when it's actually needed.

For example:

const products = document.querySelectorAll('.product-card');

if (products.length > 0) {
  products.forEach(card => {
    // Initialize only when product cards exist
  });
}
Enter fullscreen mode Exit fullscreen mode

You can also defer non-critical scripts.

<script src="{{ 'custom.js' | asset_url }}" defer></script>
Enter fullscreen mode Exit fullscreen mode

The defer attribute allows the browser to continue parsing the HTML while the script downloads.


Step 6: Don't Load an App's Assets Everywhere

This is another issue that can appear in heavily customized Shopify stores.

Suppose an app is only needed on the product page.

There is little reason to load its assets across every page if the implementation allows you to control where they are loaded.

A Liquid condition can help:

{% if request.page_type == 'product' %}
  <script src="{{ 'product-feature.js' | asset_url }}" defer></script>
{% endif %}
Enter fullscreen mode Exit fullscreen mode

Now the script is only included when the current page is a product page.

The exact implementation depends on the app and how its assets are injected, but the principle is important:

Don't load functionality where it isn't needed.


Step 7: Prevent Layout Shifts

Another common problem is images without defined dimensions.

For example:

<img src="product.jpg" alt="Product">
Enter fullscreen mode Exit fullscreen mode

The browser doesn't necessarily know how much space the image will occupy before it loads.

This can cause content to move when the image appears.

Instead:

<img
  src="product.jpg"
  alt="Product"
  width="800"
  height="800"
>
Enter fullscreen mode Exit fullscreen mode

Or use CSS with a controlled aspect ratio:

.product-image {
  aspect-ratio: 1 / 1;
  overflow: hidden;
}
Enter fullscreen mode Exit fullscreen mode

This reserves space for the image and can help create a more stable layout.


Step 8: Be Careful With Third-Party Apps

Apps are useful.

But every app can potentially add extra resources to your store.

For example:

Reviews
Chat
Analytics
Popup
Wishlist
Upsell
Tracking
Recommendations
Enter fullscreen mode Exit fullscreen mode

Individually, each one might seem small.

Together, they can create a noticeable performance cost.

Before adding another app, ask:

"Can this functionality be implemented simply in the theme?"

Sometimes a small custom Liquid/JavaScript solution can be cleaner than adding another dependency.


Step 9: A Simple Shopify Product Image Implementation

Putting some of the ideas together, a product image could look like this:

{% assign product_image = product.featured_image %}

{% if product_image %}
  <img
    src="{{ product_image | image_url: width: 1000 }}"
    srcset="
      {{ product_image | image_url: width: 400 }} 400w,
      {{ product_image | image_url: width: 800 }} 800w,
      {{ product_image | image_url: width: 1000 }} 1000w,
      {{ product_image | image_url: width: 1400 }} 1400w
    "
    sizes="(max-width: 749px) 100vw, 50vw"
    alt="{{ product_image.alt | default: product.title | escape }}"
    width="1400"
    height="1400"
    fetchpriority="high"
  >
{% endif %}
Enter fullscreen mode Exit fullscreen mode

This gives you:

  • Responsive image selection
  • Appropriate image sizing
  • Better accessibility
  • Reserved image space
  • Priority loading for the main visual

What I Would Check After Making the Changes

After making changes, don't immediately assume the page is faster.

Test it again.

Check:

Before
↓
Lighthouse / PageSpeed
↓
Make one change
↓
Test again
↓
Compare results
Enter fullscreen mode Exit fullscreen mode

Pay attention to:

  • LCP
  • CLS
  • INP
  • FCP
  • TTFB
  • Total page weight
  • Number of requests

Most importantly, check the experience on an actual mobile device.

A good Lighthouse score is useful, but real users are the final test.


The Bigger Lesson

One of the biggest mistakes in Shopify development is trying to fix performance by rebuilding everything.

Sometimes the real problem is much smaller:

One oversized image.

One unnecessary script.

One third-party app.

One poorly implemented section.

One animation running unnecessarily.

Before rebuilding a Shopify store, find the actual bottleneck.

Then fix the bottleneck.

This approach can save development time while keeping the existing store, products, theme structure, and branding intact.


Need Help With Shopify Development?

If your Shopify store needs theme customization, performance optimization, responsive design fixes, custom Liquid development, or a complete redesign, I provide Shopify development services.

You can check out my Fiverr service here:

Shopify Store Design & Development Service

If you're working with Shopify, I'd love to know:

What's the biggest performance issue you've faced in a Shopify store — images, apps, JavaScript, or something else?

Top comments (0)