Fix LCP Issues on Shopware (Loading Speed) | OpsBlu Docs

Fix LCP Issues on Shopware (Loading Speed)

Speed up Shopware LCP by enabling HTTP cache, optimizing Twig Storefront templates, compressing media images, and auditing plugin overhead.

Largest Contentful Paint (LCP) measures how quickly the main content of your Shopware store loads. Poor LCP directly impacts SEO rankings and conversion rates.

Target: LCP under 2.5 seconds Good: Under 2.5s | Needs Improvement: 2.5-4.0s | Poor: Over 4.0s

General Guide: See global LCP guide for universal concepts and fixes.

Shopware-Specific LCP Issues

1. Server Response Time (TTFB)

Shopware is a PHP-based application running on Symfony. Server response time is often the biggest LCP contributor.

Problem: Slow Time to First Byte (TTFB) delays LCP.

Diagnosis:

# Test TTFB
curl -w "@-" -o /dev/null -s https://yourstore.com << 'EOF'
    time_namelookup:  %{time_namelookup}s\n
       time_connect:  %{time_connect}s\n
    time_appconnect:  %{time_appconnect}s\n
   time_pretransfer:  %{time_pretransfer}s\n
      time_redirect:  %{time_redirect}s\n
 time_starttransfer:  %{time_starttransfer}s (TTFB)\n
                    ----------\n
         time_total:  %{time_total}s\n
EOF

# Check with Shopware profiler
# Enable in .env: APP_ENV=dev
# Then access /_profiler on any page

Solutions:

A. Upgrade PHP Version

Use PHP 8.1+ for significant performance improvements:

# Check current PHP version
php -v

# Shopware 6 supports PHP 8.1, 8.2
# Upgrade to PHP 8.2 for best performance

Performance gains:

  • PHP 8.1: 15-20% faster than 7.4
  • PHP 8.2: Additional 5-10% improvement
  • JIT compiler benefits (enable if applicable)

B. Configure OPcache Properly

Add to php.ini:

; OPcache settings for production
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0  ; Disable in production
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.enable_cli=0

; JIT (PHP 8.0+)
opcache.jit_buffer_size=100M
opcache.jit=tracing

After changing, restart PHP-FPM:

sudo systemctl restart php8.2-fpm

C. Enable and Configure Redis

Use Redis for session and cache storage:

Install Redis:

sudo apt install redis-server php-redis

Configure in .env:

# Use Redis for cache
REDIS_CACHE_HOST=127.0.0.1
REDIS_CACHE_PORT=6379
REDIS_CACHE_DATABASE=0

# Framework cache
FRAMEWORK_CACHE_ADAPTER=cache.adapter.redis

Configure in config/packages/framework.yaml:

framework:
    cache:
        app: cache.adapter.redis
        default_redis_provider: 'redis://localhost:6379'

D. Database Optimization

Optimize Database Tables:

# Run in maintenance window
bin/console database:optimize

Add Indexes for Common Queries:

-- Check slow query log
-- Add indexes for frequently queried columns
SHOW INDEX FROM product;

Use MySQL 8.0+ or MariaDB 10.5+:

  • Better query optimizer
  • Improved performance
  • JSON column support

E. Use HTTP Cache / Reverse Proxy

Enable Shopware HTTP Cache:

In .env:

SHOPWARE_HTTP_CACHE_ENABLED=1
SHOPWARE_HTTP_DEFAULT_TTL=7200

Configure Varnish (Advanced):

For high-traffic stores, use Varnish reverse proxy:

# Install Varnish
sudo apt install varnish

# Configure Shopware for Varnish
# See Shopware docs: https://docs.shopware.com/en/shopware-6-en/hosting/performance/caches

Alternative: Use Shopware Cloud or Managed Hosting:

  • Pre-configured for performance
  • Optimized server stack
  • Built-in CDN and caching

2. Unoptimized Images

Images are typically the LCP element on Shopware stores.

Problem: Large, unoptimized product or banner images loading slowly.

Diagnosis:

  • Run PageSpeed Insights
  • Check if hero/product image is flagged as LCP element
  • Look for "Properly size images" or "Serve images in next-gen formats"

Solutions:

A. Use Shopware's Image Optimization

Shopware 6 includes automatic image optimization through thumbnails.

Configure in Admin:

  1. SettingsSystemMediaThumbnail sizes
  2. Add common viewport sizes:
    • 400px (mobile)
    • 800px (tablet)
    • 1200px (small desktop)
    • 1920px (large desktop)

In Theme:

{# Use Shopware's thumbnail system #}
{% sw_thumbnails 'product-image' with {
    media: product.cover.media,
    sizes: {
        'default': '800px',
        '(max-width: 767px)': '400px',
        '(min-width: 768px) and (max-width: 1199px)': '800px',
        '(min-width: 1200px)': '1200px'
    }
} %}

B. Enable WebP Image Format

Shopware 6.4+ supports WebP images:

Admin Configuration:

  1. SettingsSystemMedia
  2. Enable Create thumbnails in WebP format
  3. Regenerate thumbnails:
bin/console media:generate-thumbnails

Template Implementation:

<picture>
    <source
        srcset="{{ product.cover.media|sw_encode_media_url }}"
        type="image/webp">
    <img
        src="{{ product.cover.media.url }}"
        alt="{{ product.cover.media.alt }}"
        width="{{ product.cover.media.metaData.width }}"
        height="{{ product.cover.media.metaData.height }}"
        loading="eager">
</picture>

C. Preload Hero Images

Add to theme's base.html.twig in <head>:

{% block layout_head_link_preload %}
    {{ parent() }}

    {% if page.header.media %}
        <link
            rel="preload"
            as="image"
            href="{{ page.header.media|sw_encode_media_url }}"
            imagesrcset="{{ page.header.media|sw_encode_media_url }} 1920w,
                         {{ page.header.media|sw_encode_media_url }} 1200w,
                         {{ page.header.media|sw_encode_media_url }} 800w"
            imagesizes="100vw">
    {% endif %}
{% endblock %}

Important: Only preload the LCP image, not all images.

D. Set Explicit Dimensions

Always include width and height to prevent layout shift:

<img
    src="{{ image.url }}"
    width="{{ image.metaData.width }}"
    height="{{ image.metaData.height }}"
    alt="{{ image.alt }}"
    loading="{% if loop.first %}eager{% else %}lazy{% endif %}">

E. Use Lazy Loading Correctly

Lazy load below-fold images only:

{# Above fold - DON'T lazy load #}
<img src="{{ heroImage.url }}" loading="eager" fetchpriority="high">

{# Below fold - DO lazy load #}
<img src="{{ productImage.url }}" loading="lazy">

3. Plugin Performance Impact

Plugins are a major cause of performance issues in Shopware.

Problem: Plugins adding render-blocking JavaScript or slow server-side processing.

Diagnosis:

Use Shopware Profiler:

# Enable profiler in .env
APP_ENV=dev

# Access profiler toolbar at page bottom
# Check "Time" and "Database" tabs

Check Plugin Impact:

# List all plugins
bin/console plugin:list

# Deactivate suspect plugins one by one
bin/console plugin:deactivate PluginName
bin/console cache:clear

Solutions:

A. Audit and Remove Unused Plugins

# List installed plugins
bin/console plugin:list

# Uninstall unused plugins
bin/console plugin:uninstall --clear-data PluginName

Regular Audit:

  • Review plugins quarterly
  • Remove those not actively used
  • Check if functionality can be achieved differently

B. Update Plugins

# Update all plugins
composer update

# Update specific plugin
composer update vendor/plugin-name

Benefits:

  • Performance improvements
  • Bug fixes
  • Security patches
  • New features

C. Defer Non-Critical Plugin JavaScript

Modify plugin templates to defer scripts:

{# In plugin template override #}
{% block base_body_script %}
    {{ parent() }}

    <script defer src="{{ asset('bundles/pluginname/js/script.js') }}"></script>
{% endblock %}

D. Use Plugin Alternatives

Instead of multiple plugins, consider:

  • Built-in Shopware features
  • GTM for tracking (instead of individual pixel plugins)
  • Lighter-weight alternatives
  • Custom development for specific needs

4. Theme JavaScript and CSS

Problem: Render-blocking CSS and JavaScript delaying LCP.

Diagnosis:

Solutions:

A. Defer Non-Critical JavaScript

In theme.json:

{
    "script": [
        {
            "path": "app/storefront/dist/storefront/js/main.js",
            "defer": true
        }
    ]
}

B. Inline Critical CSS

Extract above-fold CSS and inline it:

{% block layout_head_stylesheet %}
    <style>
        /* Critical CSS for above-fold content */
        .header { /* ... */ }
        .hero-banner { /* ... */ }
    </style>

    {{ parent() }}
{% endblock %}

C. Minify and Bundle Assets

Shopware compiles themes automatically:

# Compile theme for production
bin/console theme:compile --no-debug

# Clear cache
bin/console cache:clear --env=prod

Verify theme.json has:

{
    "style": [
        "app/storefront/src/scss/base.scss"
    ],
    "script": [
        "app/storefront/src/main.js"
    ]
}

D. Remove Unused Theme Code

Disable unused components in theme.json:

{
    "views": [
        "@Storefront",
        "@Plugins"
    ],
    "exclude": [
        "component/product/review",  // If not using reviews
        "component/wishlist"  // If not using wishlist
    ]
}

5. Third-Party Scripts

Problem: External scripts (analytics, pixels, chat) delaying LCP.

Diagnosis:

  • Network waterfall shows third-party domains
  • Scripts loading synchronously

Solutions:

A. Load Scripts Asynchronously

{# Always use async for third-party scripts #}
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXX"></script>

B. Use GTM for All Tags

  • Install GTM once
  • Add all other scripts through GTM
  • Control load timing via triggers
  • See GTM Setup

C. Delay Non-Essential Scripts

// Delay chat widget until after LCP
window.addEventListener('load', function() {
    setTimeout(function() {
        // Load chat widget here
    }, 3000);
});

6. Shopware-Specific Configurations

A. Production Mode

Always use production mode:

# .env
APP_ENV=prod
APP_DEBUG=0

Verify:

# Should show "prod"
bin/console debug:container --env-vars | grep APP_ENV

B. Cache Warming

# Warm cache after deployments
bin/console cache:warmup --env=prod

# Warm HTTP cache
bin/console http:cache:warm

C. Shopware Sales Channel Configuration

Admin → Sales Channels → Storefront:

  • Set appropriate domain
  • Configure maintenance mode correctly
  • Set correct base URL

7. CDN Configuration

Use a CDN for static assets:

Shopware Cloud has built-in CDN.

Self-Hosted Options:

  • Cloudflare (free tier available)
  • Amazon CloudFront
  • Fastly
  • KeyCDN

Configure CDN in .env:

SHOPWARE_CDN_DOMAIN=cdn.yourstore.com

8. Font Loading

Problem: Custom fonts delaying LCP.

Solutions:

A. Use System Fonts

/* Use system font stack */
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;
}

B. Optimize Web Fonts

{% block layout_head_font %}
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link
        rel="preload"
        as="style"
        href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap">
    <link
        rel="stylesheet"
        href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
        media="print"
    <noscript>
        <link
            rel="stylesheet"
            href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap">
    </noscript>
{% endblock %}

C. Self-Host Fonts

@font-face {
    font-family: 'CustomFont';
    src: url('../fonts/custom-font.woff2') format('woff2');
    font-display: swap;
    font-weight: 400;
    font-style: normal;
}

Testing & Monitoring

Test LCP

Tools:

  1. PageSpeed Insights - Lab and field data
  2. WebPageTest - Detailed waterfall
  3. Chrome DevTools - Local testing (Lighthouse panel)
  4. Shopware Profiler - Backend performance

Test Multiple Pages:

  • Homepage
  • Category pages
  • Product pages
  • Cart/Checkout

Test Different Conditions:

  • Desktop vs mobile
  • Fast 3G vs 4G
  • Different geographic locations
  • Cached vs uncached

Monitor LCP Over Time

Chrome User Experience Report (CrUX):

  • Real user data in PageSpeed Insights
  • Track trends over 28 days
  • See field data (actual users)

Google Search Console:

Third-Party Monitoring:

  • New Relic
  • Blackfire.io (PHP profiling)
  • SpeedCurve
  • Calibre

Common LCP Elements in Shopware

Page Type Common LCP Element Optimization Priority
Homepage Hero banner / slider Highest
Category First product image High
Product Main product image Highest
CMS Page Featured content image Medium
Cart Cart items (if image-heavy) Low

Quick Wins Checklist

Start here for immediate LCP improvements:

  • Upgrade to PHP 8.2
  • Configure OPcache properly
  • Enable Redis caching
  • Enable Shopware HTTP cache
  • Generate WebP thumbnails
  • Preload hero/product images
  • Set explicit image dimensions
  • Use loading="eager" on LCP image
  • Defer non-critical JavaScript
  • Remove unused plugins
  • Use production mode (APP_ENV=prod)
  • Enable theme compilation
  • Warm cache after changes
  • Use CDN for assets
  • Test with PageSpeed Insights

Advanced Optimizations

1. Use Shopware Enterprise / Managed Hosting

Benefits:

  • Pre-configured for performance
  • Optimized server stack
  • Built-in CDN
  • Automatic scaling
  • Expert support

Offload search queries from MySQL:

# Install Elasticsearch
composer require shopware/elasticsearch

# Configure in .env
OPENSEARCH_URL=http://localhost:9200

# Index data
bin/console es:index

3. Database Read Replicas

For high-traffic stores:

  • Configure read replicas
  • Distribute query load
  • Improve TTFB

4. HTTP/2 and HTTP/3

Enable on your web server for better performance:

Nginx:

listen 443 ssl http2;

Apache:

Protocols h2 http/1.1

When to Hire a Developer

Consider hiring a Shopware Expert if:

  • LCP consistently over 4 seconds after optimizations
  • Complex custom theme needs optimization
  • Database queries need optimization
  • Server configuration issues
  • Migration to better hosting needed
  • Custom plugin development required

Find Shopware Partners: store.shopware.com/en/partners

Next Steps

For general LCP optimization strategies, see LCP Optimization Guide.