Front-end performance
This documentation needs review. See "Help improve this page" in the sidebar.
Strategies
Below are some strategies that may improve site performance:
Drupal assets
-
Load libraries only when they are required. Avoid adding component-specific CSS and JavaScript to global libraries. In Drupal, libraries can be attached conditionally from preprocess functions when a particular content type, field or component is present.
For example:
function mytheme_preprocess_node(array &$variables): void { if ($variables['node']->bundle() === 'event') { $variables['#attached']['library'][] = 'mytheme/event'; } }This keeps the assets associated with the functionality that uses them and avoids downloading them on unrelated pages.
For Single Directory Components (SDC), keep component-specific CSS and JavaScript within the component directory. Drupal automatically discovers and attaches the assets declared by the component, so they do not need to be added to a global library.
- Avoid large global JavaScript libraries. If a script is only used by a carousel, map, modal or other specific component, load it with that component instead of including it on every page.
-
Use Drupal behaviors for JavaScript. Drupal behaviors provide the standard way of attaching JavaScript functionality to rendered elements. Use
once()to make sure that an element is not initialized more than once, especially when working with AJAX or dynamically rendered content.(function (Drupal, once) { Drupal.behaviors.myComponent = { attach(context) { once('my-component', '.my-component', context).forEach((element) => { // Component initialization. }); }, }; })(Drupal, once); - Keep component assets together. When possible, keep a component's CSS and JavaScript together. This makes dependencies easier to understand and avoids adding styles or scripts to the theme globally when they are only used by one component.
JavaScript and CSS
- Minify JavaScript, CSS and HTML. Remove unnecessary whitespace and development-only code from production assets.
- Aggregate JavaScript and CSS. Enable Drupal's CSS and JavaScript aggregation in production. Aggregation reduces the number of requests, but it should not be used as a reason to include assets that are not actually required by the page.
- Avoid unnecessary JavaScript dependencies. Before adding a library, check whether the functionality can be implemented using CSS, native browser APIs or existing Drupal functionality. A small piece of vanilla JavaScript is often preferable to loading a complete library for a simple interaction.
- Load non-critical JavaScript asynchronously. Scripts that are not required for the initial render should not block the browser from displaying the page. Use
deferor other appropriate loading strategies where applicable. - Remove unused CSS. Large frameworks and global stylesheets can result in considerable amounts of CSS that are never used on a particular page. Keep styles close to the components that use them and remove obsolete styles regularly.
- Use simple CSS selectors. Avoid unnecessarily complex selectors and deep nesting. Component-oriented selectors are generally easier to maintain and reduce dependencies between unrelated parts of the page.
Images and media
- Optimize images. Use Drupal image styles to generate images close to the size in which they are displayed. Avoid serving a large original image when a much smaller version is sufficient.
- Use modern image formats. WebP and AVIF can reduce image size while maintaining good visual quality. Use them where browser support and the project requirements allow it.
- Use responsive images. Drupal's Responsive Image module can be used to serve different image styles depending on the viewport. This is especially useful for large images used in cards, listings and hero components.
-
Lazy-load images that are not immediately visible. Images below the initial viewport can normally use native lazy loading:
<img src="image.webp" loading="lazy" width="800" height="600" alt="Example" >Avoid lazy-loading the main image used for the Largest Contentful Paint (LCP), as this can delay the initial render.
- Specify image dimensions. Always provide
widthandheight, or an equivalent aspect ratio, when possible. This allows the browser to reserve the required space before the image is downloaded and helps reduce Cumulative Layout Shift (CLS). - Optimize SVG files. Remove unnecessary metadata and simplify SVGs before deploying them. SVG is a good option for icons and other vector graphics where appropriate.
Rendering and Core Web Vitals
- Optimize the LCP element. Identify the element that represents the Largest Contentful Paint, which is often a hero image or the main heading. Make sure the required resources are available as early as possible and avoid unnecessary JavaScript or lazy loading delaying the element.
- Optimize fonts. Limit the number of font families and weights used by the site. WOFF2 should normally be preferred, and critical fonts can be preloaded when there is a clear benefit. Use an appropriate
font-displayvalue to avoid blocking text rendering. - Keep the DOM reasonably small. Avoid unnecessary wrapper elements and deeply nested markup. This is particularly relevant for listings and pages containing a large number of repeated components.
- Avoid unnecessary DOM manipulation. Use CSS and native browser functionality where possible. JavaScript should only modify the DOM when it is actually needed for the component behavior.
Drupal caching
- Use Drupal caching correctly. Make use of Render Cache, Dynamic Page Cache and Internal Page Cache where appropriate. Custom code should also provide the correct cache tags, contexts and max-age values so that cached output is invalidated when required.
- Use BigPipe when appropriate. BigPipe can improve perceived performance by allowing cacheable parts of a page to be displayed while dynamic content is delivered afterwards.
Third-party resources
- Limit third-party scripts. Analytics, tag managers, advertising, chat, social widgets and embedded services can add a significant amount of JavaScript and network requests. Review which integrations are really required and load them as late as possible when they are not needed for the initial render.
- Defer heavy embedded content. Maps, video players and social media embeds can introduce additional requests and JavaScript. Consider loading them only when they become visible or when the user interacts with them.
Server and asset delivery
- Use a CDN for static assets. Serving CSS, JavaScript, images and other static resources through a CDN can reduce latency for users located far from the origin server.
- Enable Brotli or gzip compression. Compress text-based responses such as HTML, CSS, JavaScript, SVG and JSON before sending them to the browser. Brotli is generally preferable when supported by the infrastructure.
- Leverage browser caching. Configure long-lived caching for static assets where possible. Versioned or aggregated asset URLs allow browsers to keep resources cached while still ensuring that updated files are downloaded when they change.
- Use preload carefully. Preload should be reserved for resources that are required very early in the page lifecycle, such as a critical font or the LCP image. Preloading too many resources can have the opposite effect by competing for network bandwidth.
- Keep inline assets small. Avoid putting large CSS, JavaScript or images directly into the HTML. Small critical styles may benefit from being inlined, but larger resources are generally better served as cacheable external assets.
Twig and markup
- Keep logic out of Twig. Twig templates should mainly deal with presentation. Expensive processing, entity loading or data preparation should be handled before rendering, for example in preprocess functions or render arrays.
Performance budget
Performance should be considered during development rather than only after a page has been completed.
Depending on the project, useful metrics to monitor include:
-
Total page weight.
-
JavaScript and CSS size.
-
Number of requests.
-
Largest Contentful Paint (LCP).
-
Interaction to Next Paint (INP).
-
Cumulative Layout Shift (CLS).
-
Time to First Byte (TTFB).
Setting a performance budget for these metrics can help prevent new components or dependencies from progressively increasing the weight of the site.
Testing
The following tools can be used to test front-end performance:
-
PageSpeed Insights provides performance measurements and Core Web Vitals information.
-
The Network tab in Chrome, Firefox, Safari and Edge DevTools can be used to inspect requests, transferred size, caching and loading times.
-
WebPageTest.org provides detailed performance tests from different locations and browsers.
-
GTmetrix provides performance reports and recommendations.
-
Lighthouse provides automated performance audits and Core Web Vitals-related diagnostics.
-
Browser DevTools can also be used to identify unused CSS and JavaScript and inspect rendering performance.
Tools
Here is a list of tools and Drupal features that can help implement the strategies above:
-
Use PageSpeed Insights to identify performance issues and monitor Core Web Vitals.
-
Use Chrome DevTools or Firefox Developer Tools to inspect network requests, cache headers, JavaScript execution and unused CSS.
-
Use Drupal's image styles and Responsive Image module to generate and serve appropriately sized images.
-
Use image optimization tools such as TinyPNG when images need to be compressed before being added to the site.
-
Use a CDN such as Cloudflare or Akamai to distribute static assets.
-
Use Drupal's aggregation and caching mechanisms in production environments.
-
Use Lighthouse or WebPageTest during development and before major releases to compare changes and identify regressions.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion