--- name: shopify-performance description: Performance optimization for Shopify stores including theme speed optimization, image optimization, JavaScript and CSS minification, lazy loading, CDN usage, caching strategies, Liquid template performance, and Core Web Vitals improvement. Use when optimizing store speed, reducing load times, improving Lighthouse scores, optimizing images, implementing lazy loading, reducing JavaScript bloat, or improving Core Web Vitals metrics (LCP, FID, CLS). --- # Shopify Performance Optimization Expert guidance for optimizing Shopify store performance including theme speed, asset optimization, and Core Web Vitals. ## When to Use This Skill Invoke this skill when: - Optimizing Shopify theme performance and load times - Improving Lighthouse or PageSpeed Insights scores - Reducing Time to Interactive (TTI) or Largest Contentful Paint (LCP) - Optimizing images for faster loading - Implementing lazy loading for images and videos - Minifying and optimizing JavaScript and CSS - Reducing JavaScript bundle sizes - Improving Core Web Vitals metrics (LCP, FID, CLS) - Implementing caching strategies - Optimizing Liquid template rendering - Reducing server response times - Improving mobile performance ## Core Capabilities ### 1. Image Optimization Images are typically the largest assets - optimize aggressively. **Use Shopify CDN Image Sizing:** ```liquid {# ❌ Don't load full-size images #} {{ product.title }} {# ✅ Use img_url filter with appropriate size #} {{ product.featured_image.alt | escape }} ``` **Responsive Images:** ```liquid {{ image.alt | escape }} ``` **Modern Image Formats:** ```liquid {# WebP for modern browsers #} {# Fallback to JPEG #} {{ image.alt | escape }} ``` **Lazy Loading:** ```liquid {# Native lazy loading #} {{ image.alt | escape }} {# Eager load above-the-fold images #} {% if forloop.index <= 3 %} {% else %} {% endif %} ``` **Preload Critical Images:** ```liquid {# In for hero images #} ``` ### 2. JavaScript Optimization Reduce JS payload and execution time. **Defer Non-Critical JavaScript:** ```html {# ❌ Blocking JavaScript #} {# ✅ Deferred JavaScript #} {# ✅ Async for independent scripts #} ``` **Inline Critical JavaScript:** ```liquid {# Inline small, critical scripts #} ``` **Code Splitting:** ```javascript // Load features only when needed async function loadCart() { const { Cart } = await import('./cart.js'); return new Cart(); } // Load on interaction document.querySelector('.cart-icon').addEventListener('click', async () => { const cart = await loadCart(); cart.open(); }, { once: true }); ``` **Remove Unused JavaScript:** ```javascript // ❌ Don't load libraries you don't use // Example: Don't include entire jQuery if you only need a few functions // ✅ Use native alternatives // Instead of: $('.selector').hide() // Use: document.querySelector('.selector').style.display = 'none'; // Instead of: $.ajax() // Use: fetch() ``` **Minify JavaScript:** ```bash # Use build tools to minify npm install terser --save-dev # Minify terser theme.js -o theme.min.js -c -m ``` ### 3. CSS Optimization Optimize stylesheets for faster rendering. **Critical CSS:** ```liquid {# Inline critical above-the-fold CSS in #} {# Load full CSS deferred #} ``` **Remove Unused CSS:** ```bash # Use PurgeCSS to remove unused styles npm install @fullhuman/postcss-purgecss --save-dev # Configure in postcss.config.js module.exports = { plugins: [ require('@fullhuman/postcss-purgecss')({ content: ['./**/*.liquid'], defaultExtractor: content => content.match(/[\w-/:]+(? tags instead */ ``` ```liquid ``` ### 4. Font Optimization Optimize web fonts for faster text rendering. **Font Loading:** ```liquid {# Preload fonts #} {# Font face with font-display #} ``` **System Font Stack:** ```css /* Use system fonts for instant rendering */ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; } ``` **Subset Fonts:** ```css /* Load only required characters */ @font-face { font-family: 'CustomFont'; src: url('font-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153; } ``` ### 5. Liquid Template Optimization Optimize Liquid rendering for faster server response. **Cache Expensive Operations:** ```liquid {# ❌ Repeated calculations #} {% for i in (1..10) %} {{ collection.products.size }} {# Calculated 10 times #} {% endfor %} {# ✅ Cache result #} {% assign product_count = collection.products.size %} {% for i in (1..10) %} {{ product_count }} {% endfor %} ``` **Use limit and offset:** ```liquid {# ❌ Iterate full array and break #} {% for product in collection.products %} {% if forloop.index > 5 %}{% break %}{% endif %} {{ product.title }} {% endfor %} {# ✅ Use limit #} {% for product in collection.products limit: 5 %} {{ product.title }} {% endfor %} ``` **Avoid Nested Loops:** ```liquid {# ❌ O(n²) complexity #} {% for product in collection.products %} {% for variant in product.variants %} {# Expensive nested loop #} {% endfor %} {% endfor %} {# ✅ Flatten or preprocess #} {% assign all_variants = collection.products | map: 'variants' | flatten %} {% for variant in all_variants limit: 50 %} {{ variant.title }} {% endfor %} ``` **Prefer render over include:** ```liquid {# ❌ include (slower, shared scope) #} {% include 'product-card' %} {# ✅ render (faster, isolated scope) #} {% render 'product-card', product: product %} ``` **Use section-specific stylesheets:** ```liquid {# Scope CSS to section for better caching #} {% stylesheet %} .my-section { /* ... */ } {% endstylesheet %} {# Scope JavaScript to section #} {% javascript %} class MySection { /* ... */ } {% endjavascript %} ``` ### 6. Third-Party Script Optimization Minimize impact of external scripts. **Defer Third-Party Scripts:** ```liquid {# ❌ Blocking third-party script #} {# ✅ Async or defer #} {# ✅ Load on user interaction #} ``` **Use Facade Pattern:** ```html {# Show placeholder instead of embedding heavy iframe #}
Video
``` ### 7. Caching Strategies Leverage browser and CDN caching. **Asset Versioning:** ```liquid {# Shopify auto-versions assets #} {# Outputs: /cdn/.../theme.css?v=12345678 #} ``` **Long Cache Headers:** ```liquid {# Shopify CDN sets appropriate cache headers #} {# CSS/JS: 1 year #} {# Images: 1 year #} ``` **Service Worker (Advanced):** ```javascript // sw.js - Cache static assets self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => { return cache.addAll([ '/cdn/.../theme.css', '/cdn/.../theme.js', '/cdn/.../logo.png', ]); }) ); }); self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(response => { return response || fetch(event.request); }) ); }); ``` ### 8. Core Web Vitals Optimization Improve Google's Core Web Vitals metrics. **Largest Contentful Paint (LCP):** ```liquid {# Optimize largest element load time #} {# 1. Preload hero image #} {# 2. Use priority hint #} {# 3. Optimize server response time (use Shopify CDN) #} {# 4. Remove render-blocking resources #} ``` **First Input Delay (FID) / Interaction to Next Paint (INP):** ```javascript // 1. Reduce JavaScript execution time // 2. Break up long tasks function processItems(items) { // ❌ Long task items.forEach(item => processItem(item)); // ✅ Break into smaller chunks async function processInChunks() { for (let i = 0; i < items.length; i++) { processItem(items[i]); // Yield to main thread every 50 items if (i % 50 === 0) { await new Promise(resolve => setTimeout(resolve, 0)); } } } processInChunks(); } // 3. Use requestIdleCallback requestIdleCallback(() => { // Non-critical work }); ``` **Cumulative Layout Shift (CLS):** ```liquid {# 1. Always set width and height on images #} Product {# 2. Reserve space for dynamic content #}
{# Content loads here #}
{# 3. Use aspect-ratio for responsive images #} ``` ### 9. Performance Monitoring Track performance metrics. **Measure Core Web Vitals:** ```javascript // Load web-vitals library import { getCLS, getFID, getLCP } from 'web-vitals'; function sendToAnalytics({ name, value, id }) { // Send to analytics gtag('event', name, { event_category: 'Web Vitals', event_label: id, value: Math.round(name === 'CLS' ? value * 1000 : value), }); } getCLS(sendToAnalytics); getFID(sendToAnalytics); getLCP(sendToAnalytics); ``` **Performance Observer:** ```javascript // Monitor long tasks const observer = new PerformanceObserver(list => { for (const entry of list.getEntries()) { console.warn('Long task detected:', entry.duration, 'ms'); } }); observer.observe({ entryTypes: ['longtask'] }); ``` ## Performance Checklist **Images:** - [ ] Use `img_url` filter with appropriate sizes - [ ] Implement responsive images with `srcset` - [ ] Add `loading="lazy"` to below-fold images - [ ] Set explicit `width` and `height` attributes - [ ] Preload critical hero images - [ ] Use modern formats (WebP) **JavaScript:** - [ ] Defer or async all non-critical scripts - [ ] Minify and bundle JavaScript - [ ] Code-split large bundles - [ ] Remove unused code - [ ] Lazy load features on interaction **CSS:** - [ ] Inline critical CSS - [ ] Defer non-critical CSS - [ ] Remove unused styles - [ ] Minify stylesheets - [ ] Avoid `@import` **Fonts:** - [ ] Preload critical fonts - [ ] Use `font-display: swap` - [ ] Consider system font stack - [ ] Subset fonts when possible **Third-Party:** - [ ] Audit all third-party scripts - [ ] Load scripts async or on interaction - [ ] Use facade pattern for heavy embeds - [ ] Monitor third-party impact **Liquid:** - [ ] Cache expensive calculations - [ ] Use `limit` instead of manual breaks - [ ] Prefer `render` over `include` - [ ] Avoid nested loops **Core Web Vitals:** - [ ] LCP < 2.5s - [ ] FID < 100ms (INP < 200ms) - [ ] CLS < 0.1 ## Best Practices 1. **Test on real devices** - Mobile 3G performance matters 2. **Use Lighthouse** for performance audits 3. **Monitor Core Web Vitals** in production 4. **Optimize above-the-fold** content first 5. **Lazy load everything else** below the fold 6. **Minimize main thread work** for better interactivity 7. **Use Shopify CDN** for all assets 8. **Version assets** for effective caching 9. **Compress images** before uploading 10. **Regular performance audits** to catch regressions ## Integration with Other Skills - **shopify-liquid** - Use when optimizing Liquid template code - **shopify-theme-dev** - Use when organizing theme assets - **shopify-debugging** - Use when troubleshooting performance issues - **shopify-api** - Use when optimizing API request patterns ## Quick Reference ```liquid {# Images #} {# Scripts #} {# Fonts #} {# Critical CSS #} {# Responsive images #} ```