Don't break your cache, use BigPipe instead.

Serving dynamic content, while maintaining the cacheability of a Drupal 8 site, used to be a tedious task. Drupal 8 did introduce a Lazy Builder way back when, but using it requires a fair amount of coding. Instead, we’ll take advantage of the BigPipe module which was included as a stable module since Drupal 8.3.

Ok, how does this work?

The main advantage of using BigPipe is that it’s fully supported, out of the box with Drupal, and requires a single change to function - all you need to do is set the cache max-age to 0. Yep, that’s it. We’ll have a look at how this can be done in a moment, but first, let’s see what happens when we do that.

After setting the max-age to 0, the block will print special placeholders, instead of the actual content. These placeholders will look something like this:

<span data-big-pipe-placeholder-id="callback=Drupal%5Cblock%5CBlockViewBuilder%3A%3AlazyBuilder&amp;args%5B0%5D=customformblock&amp;args%5B1%5D&amp;args%5B2%5D&amp;token=SLX33M5gGOLCjsQEE0JlqsYPxCKqR6tfZuEvQ1WeU4s"></span>

Drupal will also inject some magic into the drupal-settings-json script, so that it knows which parts of the page should be loaded dynamically, and update the content of those parts after the page is loaded. The result, after loading the content, will be similar to this:

<div class="custom-form" data-drupal-selector="custom-form" id="block-customformblock">
<form action="/" method="post" id="custom-form" accept-charset="UTF-8">
<input data-drupal-selector="edit-custom-form" type="hidden" name="form_id" value="custom_form">
</form>
</div>

This is cool! How do I get it working?

Since the vast majority of dynamic content on a page will come from blocks, let’s focus on those. If you want to use BigPipe with a block that is provided as part of Drupal-core or a custom module, the easiest way to change the cache settings is to implement hook_block_build_BASE_BLOCK_ID_alter in your own custom module, and alter the cache configurations of that block:

function custom_module_block_build_custom_block_alter(array &$build, BlockPluginInterface $block) {
$build['#cache']['max-age'] = 0
}

If you’re printing a custom block that you’ve developed as part of your own custom module, the solution is different but just as simple - implement the getCacheMaxAge function in your class and you’re good to go. Here is an example:

class CustomBlock extends BlockBase{

public function build() {
//....
}

public function getCacheMaxAge() {
return 0;
}

}

That’s it. You now have a fully cached page with dynamic content. The site will load faster, pages will render faster and the load on your database and server will drop considerably. Grab a coffee, you earned it.