Using cache for twig variables in preprocess function I implement a menu on a region using a preprocess function to get a link with an anchor for each block of it with a title.
I made a preprocess function for region, in my theme, where I test the region machine name.

I first used the $variables['elements'][XXX]['#id'] to load each block, to find out if the label was set to be display. But I quickly discover that on my server, where the cache is on, the $variables['elements'] only contain an array of cached render.

I then modify my preprocess hook to use the key of the $variables['elements'], witch is finally the block key.

use Drupal\block\Entity\Block;

/**
 * Implements hook_preprocess_region().
 */
function MYTHEME_preprocess_region(&amp;$variables) {
  if ($variables['region'] == 'one_page') {
    $blocs_menu = array();
    foreach ($variables['elements'] as $key =&gt; $values) {
      if (substr($key, 0, 1) == '#') {
        continue;
      }
      $bloc_object = Block::load($key);
      if (is_object($bloc_object)) {
        $bloc_settings = $bloc_object-&gt;get('settings');
        if ($bloc_settings['label_display']) {
          $blocs_menu[] = array(
              'id' =&gt; $key,
              'label' =&gt; $bloc_settings['label'],
          );
        }
      }
    }
    if (count($blocs_menu)) {
      $variables['region_menu'] = $blocs_menu;
    }
  }
}


And in my override file region--one-page.html.twig

{%- if region_menu -%}
&lt;nav class="page-nav-anchor"&gt;
  &lt;ul&gt;
{%- for menu in region_menu -%}
  &lt;li&gt;&lt;a rel="scroll" href="#block-{{ menu['id'] }}"&gt;{{ menu['label'] }}&lt;/a&gt;&lt;/li&gt;
{%- endfor -%}
  &lt;/ul&gt;
&lt;/nav&gt;
{%- endif -%}


Everything is working well, but I would like to improve the concept :


Be able to detect if the cache is activated on the project
Include in cache my 'region_menu' variable, and generate it only when cache have to be rebuild.


If I understand well, the twig template is also cached, then it is maybe just not really necessary to declare the menu if cache is ON ?

The thing is I'm really lost in the D8 cache API.
I think I have to deal with the cache tags, because I don't have a render to cache.

I would appreciate some help, I cannot find some good (and easy) examples on the documentation or in the core modules.
Regions are not cached on their own. What you build in a region template will be part of cached pages. If most pages you deliver are cached, this might be OK.

To optimize it build the menu in a block plugin and place the block at the top of the region. The block plugin can get the blocks from  BlockRepository::getVisibleBlocksPerRegion. Use the access cache metadata this method provides for the region, add cache tags for all block entities and the tag config:block_list, so that the menu block gets invalidated when the block layout is modified.