Skip to content
Snippets Groups Projects

Resolve #2232375 "Make language switcher nocache"

4 unresolved threads
Files
4
@@ -6,6 +6,7 @@
use Drupal\Core\Block\TitleBlockPluginInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Cache\CacheOptionalInterface;
use Drupal\Core\Entity\EntityViewBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -50,7 +51,6 @@ public function viewMultiple(array $entities = [], $view_mode = 'full', $langcod
// @see template_preprocess_block().
$build[$entity_id] = [
'#cache' => [
'keys' => ['entity_view', 'block', $entity->id()],
'contexts' => Cache::mergeContexts(
$entity->getCacheContexts(),
$plugin->getCacheContexts()
@@ -61,6 +61,21 @@ public function viewMultiple(array $entities = [], $view_mode = 'full', $langcod
'#weight' => $entity->getWeight(),
];
// For block plugins implementing CacheOptionalInterface, the expectation
// is that the cost of rendering them is less than retrieving them from
// cache. Only add cache keys to the block render array if the block
// plugin does not implement CacheOptionalInterface.
// If any CacheOptionalInterface block is set to render as a placeholder
// (createPlaceholder() returns TRUE), the cached response in the internal
// page cache or external caches and proxies will include the block
// markup, but the block is not cached anywhere else. If a
// CacheOptionalInterface block is not set to render as a placeholder,
// then its rendered markup is cached within the rendered page in the
// dynamic page cache.
if (!$plugin instanceof CacheOptionalInterface) {
$build[$entity_id]['#cache']['keys'] = ['entity_view', 'block', $entity->id()];
}
    • Comment on lines +64 to +69

      Doesn't this mean that the block will now bleed into the ancestors to be cached there?

      In which case, the whole point of not wanting to cache LanguageBlock seems moot as it will be render cached along with the first ancestor that specifies cache keys. Oh wait no, because we will placeholder it, we will be caching the placeholder markup with the ancestor, but not the actual rendered placeholder.

      But that still means that CacheOptionalInterface block plugins which are not placeholdered will fully be cached along with their parent. Are we fine with that?

      It does seem to imply that optional means: "Do not cache if placeholdered, cache if not". Do we want to document that?

      • But that still means that CacheOptionalInterface block plugins which are not placeholdered will fully be cached along with their parent. Are we fine with that?

        that's exactly the idea yes. There is a follow-up to use it on more blocks, see https://www.drupal.org/project/drupal/issues/3516051. things like the powered by or messages block are trivial, just one markup element, maybe a translatable string (which is cached too). It's hard to measure it reliably, but I doubt that a cache (+ currently a tag) lookup is faster than just rendering that.

      • note that even the most trivial block also involves the block template and preprocess, but still, I think external lookup is slower, especially if have a larger site with a cluster and DB/redis through a network.

      • that's exactly the idea yes

        Okay, then maybe we need to document that? We know how it works, but not everyone knows how the renderer and render cache work in detail. Just a small hint that caching may still occur further up the tree and if you want to avoid that, you should placeholder the block.

      • Agreed that documenting this is a good idea, but yeah the idea here is that:

        • cache optional and placeholdered blocks are still cached by the internal page cache or proxies (so not max-age 0), but not anywhere else.
        • cache optional blocks that aren't placeholders are still cached by dynamic page cache, just not individually - when we think the cost of rendering them directly on a dynamic render cache miss might be less than cache retrieval.
      • Added documentation.

      • Please register or sign in to reply
Please register or sign in to reply
// Allow altering of cacheability metadata or setting #create_placeholder.
$this->moduleHandler->alter(['block_build', "block_build_" . $plugin->getBaseId()], $build[$entity_id], $plugin);
Loading