Fix Slow LCP on Liferay (Speed Guide) | OpsBlu Docs

Fix Slow LCP on Liferay (Speed Guide)

Reduce Liferay LCP by enabling portal page caching, optimizing Adaptive Media image variants, and minifying theme module CSS/JS.

General Guide: See Global LCP Guide for universal concepts and fixes.

What is LCP?

Largest Contentful Paint measures when the largest content element becomes visible. Google recommends LCP under 2.5 seconds. Liferay DXP is a Java-based portal platform. LCP is driven by page cache configuration, Adaptive Media image processing, and theme/portlet asset loading.

Liferay-Specific LCP Causes

  • Portal page cache disabled -- without caching, Liferay renders every page through the full portlet lifecycle (init, processAction, render), resulting in 1-5s TTFB
  • Adaptive Media not configured -- Liferay's Adaptive Media module generates responsive image variants, but requires configuration
  • Theme CSS/JS not minified -- Liferay themes can include unminified frontend assets
  • Portlet render chain -- each portlet on a page renders independently, and slow portlets block the entire page
  • Fragment rendering overhead -- Liferay 7.x Content Pages use fragments that each require separate rendering

Fixes

1. Enable Page Caching

Configure Liferay's built-in page cache:

# portal-ext.properties
# Enable Ehcache-based page caching
ehcache.multi.vm.config.location=/ehcache/liferay-multi-vm-clustered.xml
layout.cache.enabled=true

# Set cache size and TTL
layout.cache.max.size=10000
layout.cache.ttl=3600

Or use the Admin Panel: Control Panel > Configuration > System Settings > Infrastructure > Cache

2. Configure Adaptive Media

Set up image resolutions at Control Panel > Configuration > Adaptive Media:

Resolution: Hero (1920x600)
Resolution: Thumbnail (400x300)  
Resolution: Mobile Hero (640x320)

In your theme's FreeMarker templates:

<#-- Use Adaptive Media for responsive hero images -->
<#assign heroImage = journalArticle.getDocument().selectSingleNode("//dynamic-element[@name='heroImage']/dynamic-content")>
<#if heroImage?has_content>
  <img
    src="${heroImage.getText()}"
    srcset="
      ${adaptiveMedia.getAdaptiveMediaURL(heroImage.getText(), 640, 320)} 640w,
      ${adaptiveMedia.getAdaptiveMediaURL(heroImage.getText(), 1024, 400)} 1024w,
      ${adaptiveMedia.getAdaptiveMediaURL(heroImage.getText(), 1920, 600)} 1920w"
    sizes="100vw"
    width="1920" height="600"
    alt="${title}"
    loading="eager"
    fetchpriority="high"
  >
</#if>

3. Minify Theme Assets

In your Liferay theme's liferay-look-and-feel.xml:

<look-and-feel>
  <theme id="mytheme" name="My Theme">
    <settings>
      <setting key="minified-css" value="true" />
      <setting key="minified-js" value="true" />
    </settings>
  </theme>
</look-and-feel>

Enable portal-wide minification:

# portal-ext.properties
minifier.enabled=true
theme.css.fast.load=true
theme.images.fast.load=true
javascript.fast.load=true

4. Optimize Portlet Rendering

Identify slow portlets using Liferay's built-in profiling:

# Enable portlet render timing
portlet.container.render.timeout=5000

Cache portlet output:

<!-- In portlet.xml -->
<portlet>
  <portlet-name>MyPortlet</portlet-name>
  <expiration-cache>3600</expiration-cache>
</portlet>

5. Preload Critical Assets

<#-- In theme's portal_normal.ftl -->
<link rel="preconnect" href="${themeDisplay.getCDNBaseURL()}" />
<link rel="preload" as="image" href="${heroImageURL}" />
<link rel="preload" as="style" href="${themeDisplay.getPathThemeCSS()}/main.css" />

Measuring LCP on Liferay

  1. Liferay's Performance tab (Control Panel) -- shows page render times per portlet
  2. Gogo Shell -- cache:listAll shows cache statistics
  3. PageSpeed Insights -- test key portal pages
  4. JMX monitoring -- connect JConsole for JVM-level performance data

Analytics Script Impact

Liferay's analytics integration (Analytics Cloud) is built-in and loads asynchronously. For third-party analytics, add via theme modules with async/defer attributes.