The problem is, that the cache tag block_content:[id]
does not bubble up and the tag is missing in the cache entry. Without this cache tag the cache entry can't be invalidated when saving a modified custom block.
TwoHere are two workarounds:
Twig template (Workaround 1)
If you theme a block template and you render single fields
{{ content.field_field1 }}
{{ content.field_field2 }}
then you also need to render the rest of content
:
{{ content.withoutcontent|without('field_field1', 'field_field2') }}
That's because content
contains the cache tag of the block content entity, which otherwise won't bubble up.
Preprocess (Workaround 2)
As an alternative option for rendering {{ content }}
you can add the cache tag at the top of variables
in preprocess.
mytheme.theme
function mytheme_preprocess_block(&$variables) {
if ($variables['base_plugin_id'] == 'block_content') {
$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($variables, $variables['content']['#block_content']);
}
}
Then you no longer depend on the twig template to render all of content
.
You'll find in Drupal\block\BlockViewBuilder::preRender()
more workarounds for issues with bubbling up data from the content render array. You could use this code, which there is only applied in special circumstances, for all cache data from block content to bubble up to the top level:
use Drupal\Core\Cache\CacheableMetadata;
function mytheme_preprocess_block(&$variables) {
$content = $variables['content'];
CacheableMetadata::createFromRenderArray($variables)
->merge(CacheableMetadata::createFromRenderArray($content))
->applyTo($variables);
}
But I don't know which side effects that would have in other places. If it would be that easy the block view builder would do this already. So it's better to tackle only that specific problem with the one missing tag and use the first version of the preprocess function.