Thanks to its newly improved Cache API, Drupal 8 is faster than ever. Drupal 8 performance configuration is available on /admin/config/development/performance.

Now enabled by default, a new core module called Internal Page Cache caches pages for anonymous users. Pages requested by anonymous users are stored and reused, speeding up performance.

The only changeable setting in the Internal Page Cache is the "Page cache maximum age”, which sets the max-age value in the Cache-Control headers output by Drupal 8. Set the max-age as high as the frequency with which you are updating the pages. If your site will be getting a lot of traffic, set the max-age to a higher value. The higher the max-age, the better the information that is being cached and reused. Your CDN and frontend caching, such as Varnish, will utilize the max-age and serve the cached copy until it expires. To disable caching for development purposes, set the "Page cache maximum age" to no caching. The only value that will disable Drupal's caching is "no caching".

This module assumes pages are identical for all anonymous users. So if your website is serving personalized content, you will want to disable the Internal Page Cache module. Otherwise, Javascript and Ajax can handle the personalization on the front-end. 

Alternatively, you can use Dynamic Page Cache. Dynamic Page Cache caches the pages minus the personalized sections. Hence, this is useful for both anonymous and authenticated users. Dynamic Page Cache uses the cache contexts, a declarative way to create context variations of all the items to be cached. These dynamic sections are marked with placeholders by Drupal 8 Render API, called auto-placeholdering. A placeholder is assigned and Drupal will postpone the rendering of the placeholder render array until the very last moment. The overall page with auto-placeholdering is cached by Dynamic Page Cache and Drupal continues to render cache fragments for those dynamic parts.

Read more on Internal Page Cache.

Read more on Dynamic Page Cache.

Read more on Auto-placeholdering.

Cache API

For developers working on Drupal 8, caching is a compulsory topic, it is important to learn and understand the basics of the Cache API. 

Cache contexts

Cache contexts are analogous to HTTP's Vary header. It determines the context involved in the caching of a render array. Cache contexts are represented in sets of strings. Examples cache contexts are

  • languages (vary by all language types: interface, content, …)

  • languages:language_interface (vary by interface language)

  • user.roles (vary by user’s role)

  • url (vary by the entire url)

  • url.path.is_front (vary by the front page)

Read more on Cache Contexts.

Cache tags

Cache tags show what data that the cache depends on to Drupal. Similar to cache contexts, cache tags are represented in sets of strings. A cache will be invalidated when a cache tag is matched. 

For example:

  • user:10 (invalidates the cache when User entity 10 changes)

  • node:8 (invalidates the cache when Node entity 8 changes)

Read more on Cache Tags.

Cache max-age

Cache max-age determines the number of seconds the cache item is valid. Generally, you don’t need to set a max-age, relying on the default (Cache::PERMANENT) will do.

Read more on Cache max-age.

Debugging cache

You can debug cacheable responses by setting the http.response.debug_cacheability_headers parameter to true in your services.yml. For this to take effect, the container must be rebuilt. That will cause Drupal to send the corresponding X-Drupal-Cache-Tags and X-Drupal-Cache-Contexts headers to cache tags and cache contexts.

Using cache contexts and cache tags

Use \Drupal\node\Entity\Node;

/**

 * Implements hook_preprocess_block().

 */

function mymodule_preprocess_block(&$variables) {

  if ($variables['elements']['#id'] == 'search_promo') {

    // Unique cache per search query string.

    $variables['#cache']['contexts'] = ['url.query_args:search'];

    // Depends on content from a node entity.

    $node = Node::load($variables['promo_nid']);

    $variables['#cache']['tags'] = [$node->getCacheTags(];

  }

}

Let’s say that we have a promo content block which will display different content based on the searches performed. The “search” query string will determine the cache context of the block. The block will be cached vary on the “search” query string, hence the url.query_args:search. The cache tags indicate that the cached block should be invalidated when the node entity content, where the block is loading, is updated.

Generally cache tags take the form of <entity type ID>:<entity ID> or config:<configuration name>, you should not rely on these directly. You should retrieve cache tags to invalidate for a single entity using its ::getCacheTags() method, e.g. $node->getCacheTags(), $user->getCacheTags(), $view->getCacheTags() etc.

To invalidate a cache use Drupal\Core\Cache\Cache;

Cache::invalidateTags($node->getCacheTags());

What are the available cache contexts 

A quick trick to find the list of cache contexts you could use, search the files *.services.yml for cache_context.*.

Gotchas

  • The {{ content }} variable in template

You must render the {{ content }} variable to ensure that its cache tags bubble up and end up in the page cache. You may end up with an uncacheable page if the {{ content }} is not rendered.

So ensure your template contains:

{{ content }}

Or if you would like to render some fields separately

{{ content|without('field_coauthor', 'field_more_link') }}

  • Avoid random sort
    A random sort in views or code will cause the page to be not cacheable.

  • All access-checking logic must now return AccessResultInterface objects, allows for cacheability metadata. If you implement any form of access or alter existing access hooks, ensure you return one of these:

    • return AccessResult::allowed();

    • return AccessResult::forbidden();

    • return AccessResult::neutral(); // The default if all conditions failed.

Read more on AccessResultInterface.

Share your ideas, thoughts and suggestions

Change Customer Behavior, Drive Digital Revenues

==

Learn how the right digital data and analytics can help you change customer behavior as they interact with your website, ads, and digital ecosystem, thus producing exponential ROI.