Placeholders/#lazy_builder is not supported for block component rendering

Created on 11 April 2025, about 1 month ago

Overview

📌 Add support for Blocks as Components Active added support for block components.

However the block rendering directly renders the block plugin using $block->build() without support for automatic placeholdering of blocks.

Automatic placeholdering of blocks is supported by block module in BlockViewBuilder::viewMultiple().

It is not supported in layout builder, but there is an open issue since 2019 to fix that 📌 Support auto-placeholdering for blocks placed in Layout Builder Needs work .

Proposed resolution

I have a feeling that the logic from BlockViewBuilder::viewMultiple() to build the render array could be copied more or less into the block component plugin, doesn't seem like it would need a huge refactor or anything.

Note that BlockPluginInterface now supports a ::createPlaceholder() method since 📌 Create placeholders for more things Active as of 11.2, that might need a method exists check for earlier Drupal versions but would be good to respect that since it leads to significant performance improvements with the current state of 11.2 as well as various in-progress issues.

User interface changes

🐛 Bug report
Status

Active

Version

0.0

Component

Component sources

Created by

🇬🇧United Kingdom catch

Live updates comments and jobs are added and updated live.
  • Performance

    It affects performance. It is often combined with the Needs profiling tag.

Sign in to follow issues

Comments & Activities

  • Issue created by @catch
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Well-spotted!

  • 🇪🇸Spain penyaskito Seville 💃, Spain 🇪🇸, UTC+2 🇪🇺
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Two observations:

    1. We can't use exactly as-is, because that uses Block config entities; whereas XB uses the underlying block plugins directly. Still, exactly the same pattern can be applied! 👍
    2. With one important exception (identified by @penyaskito!): block plugins whose rendering is delayed (by the use of Render API placeholders to execute #lazy_builders as late as possible) prevent emptiness checks necessary only when rendering XB previews

    So, I think we'll want to do something conditional: use the current code path when previewing, use what @catch proposes for end users. That'd look roughly like what's in the attached PoC patch — but lots of details left to get right.

    Thoughts?

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    Let's first land 📌 Test coverage to prove that BlockPluginInterface cacheability + BigPipe support work when rendered via XB Active , which will clearly demonstrate the problem 👍

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
  • 🇨🇭Switzerland berdir Switzerland

    I don't know too much about XB yet, but I tried a long time ago to do this with page manager, which turned out to be hard to impossible.

    A lazy builder must be able to pass all necessary information as a serialized string.

    block.module blocks are 100% standalone and isolated, identified just by their config entity ID, so that's easy. The problem for page manager was context (the block/plugin context system). For example, you could have a view with a term argument, and on the page manager page, you have multiple terms as context that you pass in to the various views blocks.

    I think XB does not currently have anything like that and not sure if it ever will. But even then, you don't just have a string/ID, You have the whole configuration set for a given block, which might very well include internal information, maybe you have a block with an API key in the config or something like that. So that can't just be serialized out into the HTML placeholder, might also be quite long. Maybe some kind of key-value lookup, a bit like the configuration for entity autocomplete form elements.

  • 🇬🇧United Kingdom catch

    You have the whole configuration set for a given block, which might very well include internal information, maybe you have a block with an API key in the config or something like that.

    The lazy builder could take the entity ID of the config or content entity, load it, and then find the config for the block in there. It would need enough information to locate it though, not sure what all of that would be (field name at least on entities etc.) but should be finite.

Production build 0.71.5 2024