Magento LCP Optimization
Largest Contentful Paint (LCP) measures how long it takes for the main content of a page to load. For Magento 2 stores, poor LCP often stems from unoptimized images, slow server response times, and inadequate caching. This guide provides comprehensive solutions for achieving LCP under 2.5 seconds.
Understanding LCP in Magento
What is LCP?
Largest Contentful Paint measures the time from when a page starts loading to when the largest visible element (image, video, or text block) is rendered.
Google's LCP Thresholds:
- Good: ≤ 2.5 seconds
- Needs Improvement: 2.5 - 4.0 seconds
- Poor: > 4.0 seconds
Common LCP Elements in Magento
- Homepage: Hero banner images, carousel images
- Category Pages: Category banner, first product images
- Product Pages: Main product image
- Checkout: Page header, cart summary
Measuring LCP
1. Chrome DevTools
Steps:
- Open DevTools (F12)
- Go to Performance tab
- Click Record and reload page
- Stop recording
- Look for "LCP" marker in timeline
2. PageSpeed Insights
Visit: https://pagespeed.web.dev/
- Enter your Magento URL
- Check "Field Data" for real-user metrics
- Check "Lab Data" for simulated results
3. Lighthouse
CLI:
lighthouse https://your-store.com --view
Chrome DevTools:
- Open DevTools > Lighthouse tab
- Select Performance
- Generate report
4. Web Vitals Chrome Extension
Install: Web Vitals Extension
- Real-time LCP measurement
- Color-coded indicators
- Historical data tracking
Full Page Cache (FPC) Optimization
Enable and Configure FPC
1. Enable Built-in FPC:
php bin/magento config:set system/full_page_cache/caching_application 1
php bin/magento cache:enable full_page
php bin/magento cache:flush
2. Configure FPC Settings:
Stores > Configuration > Advanced > System > Full Page Cache
- Caching Application: Built-in Cache or Varnish
- TTL for public content: 86400 (1 day)
3. Verify FPC is Working:
curl -I https://your-store.com/ | grep X-Magento-Cache
Expected: X-Magento-Cache-Control: max-age=86400, public
Cache Warming
Pre-populate cache for better LCP on first visit.
Install Cache Warmer:
composer require jeroenvermeulen/magento2-cache-warmer
php bin/magento module:enable JeroenVermeulen_CacheWarmer
php bin/magento setup:upgrade
Configure:
Stores > Configuration > System > Cache Warmer
Manual Cache Warming:
php bin/magento cache:warm
Varnish Configuration
Varnish provides superior caching performance compared to built-in FPC.
Install and Configure Varnish
1. Install Varnish:
# Ubuntu/Debian
apt-get install varnish
# CentOS/RHEL
yum install varnish
2. Generate Varnish VCL:
php bin/magento varnish:vcl:generate --export-version=6 > /etc/varnish/magento.vcl
3. Configure Magento for Varnish:
Stores > Configuration > Advanced > System > Full Page Cache
4. Varnish Configuration:
File: /etc/varnish/default.vcl
vcl 4.0;
import std;
backend default {
.host = "127.0.0.1";
.port = "8080";
.first_byte_timeout = 600s;
.between_bytes_timeout = 600s;
}
acl purge {
"localhost";
"127.0.0.1";
}
sub vcl_recv {
if (req.method == "PURGE") {
if (client.ip !~ purge) {
return (synth(405, "Method not allowed"));
}
return (purge);
}
if (req.url ~ "^/(pub/)?(media|static)/") {
# Static files should always be cached
return (hash);
}
if (req.http.Cookie ~ "X-Magento-Vary=") {
# Vary cookie exists, handle accordingly
set req.http.X-Magento-Vary = regsub(req.http.Cookie, ".*X-Magento-Vary=([^;]+);*.*", "\1");
}
return (hash);
}
sub vcl_backend_response {
# Cache static content for 1 year
if (bereq.url ~ "^/(pub/)?(media|static)/") {
set beresp.ttl = 365d;
set beresp.http.Cache-Control = "public, max-age=31536000";
}
# Set grace period
set beresp.grace = 5m;
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Magento-Cache-Debug = "HIT";
} else {
set resp.http.X-Magento-Cache-Debug = "MISS";
}
}
5. Start Varnish:
systemctl enable varnish
systemctl start varnish
6. Verify Varnish:
curl -I https://your-store.com/ | grep X-Magento-Cache-Debug
Expected: X-Magento-Cache-Debug: HIT (after second request)
Varnish Performance Tuning
File: /etc/varnish/varnish.params
VARNISH_STORAGE="malloc,4G" # Increase cache size
VARNISH_TTL=120 # Default TTL in seconds
DAEMON_OPTS="-p thread_pools=4 \
-p thread_pool_min=100 \
-p thread_pool_max=5000"
Image Optimization
Images are often the LCP element. Optimize them for faster loading.
1. WebP Conversion
Convert images to WebP format for better compression.
Install WebP Module:
composer require magento/module-page-builder-webp
php bin/magento module:enable Magento_PageBuilderWebp
php bin/magento setup:upgrade
Manual Conversion:
# Install cwebp tool
apt-get install webp
# Convert images
find pub/media/catalog/product -name "*.jpg" -exec bash -c 'cwebp -q 80 "$0" -o "${0%.jpg}.webp"' {} \;
2. Lazy Loading
Prevent off-screen images from blocking LCP.
Native Lazy Loading:
File: view/frontend/templates/product/image.phtml
<img src="<?= $block->getImageUrl() ?>"
alt="<?= $block->getLabel() ?>"
loading="lazy"
width="<?= $block->getWidth() ?>"
height="<?= $block->getHeight() ?>" />
JavaScript Lazy Loading (for older browsers):
File: view/frontend/templates/lazyload.phtml
<script>
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
}
});
</script>
3. Image Optimization Tools
Optimize Existing Images:
# Install optimization tools
apt-get install jpegoptim optipng
# Optimize JPG images
find pub/media -name "*.jpg" -exec jpegoptim --strip-all --max=85 {} \;
# Optimize PNG images
find pub/media -name "*.png" -exec optipng -o7 {} \;
Automated Optimization with Magento Extension:
composer require creativestyle/magesuite-image-optimizer
php bin/magento module:enable Creativestyle_ImageOptimizer
php bin/magento setup:upgrade
4. Responsive Images
Serve appropriately sized images for different devices.
File: view/frontend/templates/product/image.phtml
<img src="<?= $block->getImageUrl() ?>"
srcset="<?= $block->getSmallImageUrl() ?> 480w,
<?= $block->getMediumImageUrl() ?> 768w,
<?= $block->getLargeImageUrl() ?> 1200w"
sizes="(max-width: 480px) 100vw,
(max-width: 768px) 50vw,
33vw"
alt="<?= $block->getLabel() ?>"
width="1200"
height="1200" />
5. Preload LCP Image
Preload the hero image to improve LCP.
File: view/frontend/layout/cms_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<head>
<link rel="preload" as="image" href="{{media url='wysiwyg/hero-banner.jpg'}}" />
</head>
</page>
Dynamic Preload in Template:
<?php if ($block->getHeroImage()): ?>
<link rel="preload" as="image" href="<?= $block->getHeroImage() ?>" />
<?php endif; ?>
Server Optimization
1. Enable HTTP/2
HTTP/2 improves resource loading through multiplexing.
Apache:
File: /etc/apache2/mods-available/http2.conf
<IfModule http2_module>
Protocols h2 h2c http/1.1
</IfModule>
Enable module:
a2enmod http2
systemctl restart apache2
Nginx:
File: /etc/nginx/sites-available/magento
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# ... rest of config
}
Reload Nginx:
nginx -t
systemctl reload nginx
2. Enable HTTP/3 (QUIC)
Nginx with QUIC (experimental):
server {
listen 443 quic reuseport;
listen 443 ssl http2;
ssl_protocols TLSv1.3;
add_header Alt-Svc 'h3=":443"; ma=86400';
}
3. Optimize PHP
Install OPcache:
apt-get install php8.1-opcache
Configure OPcache:
File: /etc/php/8.1/fpm/conf.d/10-opcache.ini
opcache.enable=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=32531
opcache.validate_timestamps=0 # Disable in production
opcache.save_comments=1
opcache.fast_shutdown=1
Restart PHP-FPM:
systemctl restart php8.1-fpm
4. Optimize MySQL
File: /etc/mysql/my.cnf
[mysqld]
innodb_buffer_pool_size = 4G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
query_cache_size = 64M
query_cache_limit = 2M
table_open_cache = 4000
Restart MySQL:
systemctl restart mysql
Redis Configuration
Redis improves cache and session performance.
Install Redis
apt-get install redis-server php-redis
systemctl enable redis-server
systemctl start redis-server
Configure Magento for Redis
File: app/etc/env.php
'cache' => [
'frontend' => [
'default' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => '127.0.0.1',
'port' => '6379',
'database' => '0',
'compress_data' => '1'
]
],
'page_cache' => [
'backend' => 'Cm_Cache_Backend_Redis',
'backend_options' => [
'server' => '127.0.0.1',
'port' => '6379',
'database' => '1',
'compress_data' => '0'
]
]
]
],
'session' => [
'save' => 'redis',
'redis' => [
'host' => '127.0.0.1',
'port' => '6379',
'database' => '2',
'compression_threshold' => '2048',
'compression_library' => 'gzip',
'max_concurrency' => '6',
'break_after_frontend' => '5',
'break_after_adminhtml' => '30',
'first_lifetime' => '600',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'disable_locking' => '0'
]
]
Redis Performance Tuning
File: /etc/redis/redis.conf
maxmemory 2gb
maxmemory-policy allkeys-lru
save "" # Disable persistence for cache
Restart Redis:
systemctl restart redis-server
CDN Implementation
Use a CDN to serve static assets faster globally.
Configure CDN in Magento
Stores > Configuration > General > Web
- Base URL for Static View Files:
https://cdn.yourstore.com/static/ - Base URL for User Media Files:
https://cdn.yourstore.com/media/
Popular CDN Options
- Cloudflare - Free tier available, easy setup
- Fastly - Official Magento partner (Adobe Commerce)
- AWS CloudFront - AWS integration
- KeyCDN - Affordable, good performance
- BunnyCDN - Cost-effective option
Critical CSS
Inline critical CSS to prevent render blocking.
Extract Critical CSS
Using Critical CSS Generator:
npm install -g critical
critical https://your-store.com/ \
--base pub/static/ \
--inline \
--minify \
--width 1300 \
--height 900 \
> critical.css
Inline Critical CSS
File: view/frontend/layout/default.xml
<head>
<style type="text/css">
/* Inline critical CSS here */
body{margin:0;padding:0}
.page-header{background:#000;color:#fff}
/* ... */
</style>
</head>
Defer Non-Critical CSS
File: view/frontend/layout/default.xml
<head>
<css src="css/styles.css" defer="defer"/>
</head>
Font Optimization
Preload Fonts
File: view/frontend/layout/default.xml
<head>
<link rel="preload" as="font" type="font/woff2"
href="{{static url='fonts/opensans-regular.woff2'}}"
crossorigin="anonymous"/>
</head>
Use font-display: swap
File: web/css/source/_typography.less
@font-face {
font-family: 'Open Sans';
src: url('../fonts/opensans-regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap; /* Prevents invisible text */
}
JavaScript Optimization
Defer JavaScript
File: view/frontend/requirejs-config.js
var config = {
deps: [], // Remove synchronous dependencies
shim: {}
};
Minimize JavaScript Bundling
php bin/magento config:set dev/js/enable_js_bundling 0
php bin/magento config:set dev/js/minify_files 1
php bin/magento config:set dev/js/merge_files 0
Testing & Validation
Before/After Comparison
Test with WebPageTest:
- Visit webpagetest.org
- Enter URL
- Select test location
- Run test
- Compare LCP metrics
Continuous Monitoring
- Monitor Core Web Vitals report
- Track field data from real users
- Identify problematic URLs
Chrome User Experience Report (CrUX):
# Install CrUX API tool
npm install -g crux
# Query your site
crux https://your-store.com/
Quick Wins Checklist
- Enable Full Page Cache (FPC)
- Implement Varnish caching
- Configure Redis for cache and sessions
- Enable HTTP/2
- Optimize and compress images
- Implement lazy loading for images
- Preload LCP image
- Use WebP image format
- Enable OPcache for PHP
- Configure CDN for static assets
- Inline critical CSS
- Optimize font loading
- Minimize JavaScript blocking
Next Steps
- CLS Optimization - Fix layout shift issues
- Tracking Issues - Debug analytics
- Magento DevDocs - Performance best practices
Additional Resources
- Web Vitals - Google's Core Web Vitals guide
- PageSpeed Insights - Performance testing tool
- Magento Performance Toolkit - Load testing
- Varnish Documentation - Varnish cache guide