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 Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Render\Renderer;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\sdm_user\SdmUserSalesforceClient;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Response;
/**
* Provides route responses for the Example module.
*/
class myController extends ControllerBase {
/**
* @var \Drupal\Core\Render\Renderer
*/
private $renderer;
/**
* @param \Drupal\Core\Render\Renderer $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 = \Drupal\views\Views::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 block\thing in the site that will suffer this problem?
Isn't there a module\API\some approach that can generally solve this problem, without custom specific code for every element?
max-age
- I'm usinghook_views_pre_view
for that - or most probably because of the issue linked in the 1st link. The solution relying on tags of the 1st link actually works, but client would like to have that block strictly refresh every reload. That would need to set up an extremely aggressive cron - like every 5s - and still not doing exactly what the client want.