8 – How to deal with block cached for anonymous user?

I have placed in the site’s home, via twig, a views block of nodes with a random sort and obliviously no cache active.
Therefore, at each page reload different nodes appear.

The problem is that block get still cached for anonymous users.

For now, we can’t yet do performance test of the site, so we’d rather not disable the Internal Page Cache module.

The Internal page documentation says:

Websites that serve personalized content to anonymous users (dynamic, per-session, e.g. a shopping cart) will want to disable the Internal Page Cache module. This module assumes pages are identical for all anonymous users. Those websites can still take advantage of the Dynamic Page Cache module though, or can alternatively do their personalization using JavaScript + AJAX.

So after failing to find anything else useful, I’ve tried this solution to solve the issue.

Unfortunately I found no module that let “load” the block via ajax, or something similar. For now I’ve implemented a custom route that render the block view:

<?php

namespace Drupalmy_moduleController;

use DrupalCoreControllerControllerBase;
use DrupalCoreLoggerLoggerChannelFactoryInterface;
use DrupalCoreRenderRenderer;
use DrupalCoreSessionAccountProxyInterface;
use Drupalsdm_userSdmUserSalesforceClient;
use SymfonyComponentDependencyInjectionContainerInterface;
use SymfonyComponentHttpFoundationResponse;

/**
 * Provides route responses for the Example module.
 */
class myController extends ControllerBase {

  

  /**
   * @var DrupalCoreRenderRenderer
   */
  private  $renderer;

  /**
   * @param DrupalCoreRenderRenderer $renderer
   */
  public function __construct(Renderer $renderer){
    $this->renderer = $renderer;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('renderer')
    );
  }

  /**
   * @return array
   *   A simple renderable array.
   */
  public function render($id, $display) {
    $view = DrupalviewsViews::getView($id);
    $render_array = $view->buildRenderable($display);
    $rendered = $this->renderer->renderRoot($render_array);
    $response = new Response();
    $response->setContent($rendered);
   
    return $response;

  }
}

And then in a custom js, load the necessary block via ajax:

(function ($, Drupal, drupalSettings) {
    Drupal.behaviors.products_in_home = {
        attach: function (context, settings) {
            $(document, context).once('products_in_home').each(function () {
                jQuery.ajax({
                    url: drupalSettings.path.currentLanguage + '/ajax/views/prodotti/products',
                    method: 'GET',
                    success: function (data) {
                        $(".products-container-home").html(data);
                    }
                });
            });
        }
    }
}(jQuery, Drupal, drupalSettings));

This works, but I’m kinda baffled: is this the only approach possible?

I mean, do I need to manually load via ajax every blockthing in the site that will suffer this problem?

Isn’t there a moduleAPIsome approach that can generally solve this problem, without custom specific code for every element?