Anonyme Benutzer-Cache-Steuerung


7

Wir haben einige benutzerdefinierte Blöcke geschrieben, die dynamischen Inhalt rendern. Leider wird beim Caching standardmäßig das erste Rendering dieses Blocks zwischengespeichert (und für anonyme Benutzer nicht aktualisiert). Die Cache-Steuerung scheint nur für authentifizierte Benutzer zu funktionieren. Vermissen wir etwas Offensichtliches? Ist es möglich, anonymes Caching auf Block- (oder Seiten-) Basis zu steuern?


Ist der Block in einem Modul implementiert?
Kiamlaluno

Antworten:


11

Es gibt zwei verschiedene Seiten-Caches.

Der interne dynamische Seiten-Cache funktioniert mit allen Arten von Elementen wie Blöcken und Knoten und verwendet die von diesen Elementen bereitgestellten Cache-Tags, Cache-Kontexte und das maximale Cache-Alter.

Der interne Seiten- Cache ist für vollständige Seiten für anonyme Benutzer vorgesehen und verwendet nur Cache-Tags.

Sie können den Seitencache für anonyme Benutzer mit einem Parameter steuern.

Gehen Sie zur Leistungskonfiguration:

admin/config/development/performance

Konfigurieren Sie das maximale Alter des Seitencaches mit der Zeit, wie lange Ihre Informationen gültig sind. Dies ist auch für Proxys und den Browser-Cache wichtig, da es nicht hilfreich wäre, den Drupal-Cache ungültig zu machen, wenn die Seite an anderen Stellen zwischengespeichert wird. Nach dieser Zeit läuft die Seite ab und sollte erneut erstellt werden. Laut Dokumentation:

Konfigurieren des internen Seitencaches Auf der Seite Leistung können Sie konfigurieren, wie lange Browser und Proxys Seiten zwischenspeichern dürfen. Diese Einstellung wird auch vom internen Seiten-Cache-Modul berücksichtigt. Es gibt keine andere Konfiguration.

Aber das ist nicht wahr. Sie sollten diese Zeit für Proxys und den Browser-Cache konfigurieren, aber der interne Seiten-Cache berücksichtigt nicht die Zeit, die Sie dort festgelegt haben. Die einzige zuverlässige Lösung, die ich gefunden habe, besteht darin, den internen Seiten- Cache des Moduls zu deinstallieren oder eine Ablaufzeit in einem EventSubscriber festzulegen (z. B. 3600 Sekunden in der Zukunft):

/src/EventSubscriber/SetExpiresSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class SetExpiresSubscriber implements EventSubscriberInterface {

  public function onResponse(FilterResponseEvent $event) {
    $request = $event->getRequest();
    $response = $event->getResponse();
    if ($event->isMasterRequest()) {
      $request_time = $request->server->get('REQUEST_TIME');
      $expires_time = (new \Datetime)->setTimestamp($request_time + 3600);
      $response->setExpires($expires_time);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['onResponse'];
    return $events;
  }

}

mymodule.services.yml

services:
  mymodule.setexpires:
    class: Drupal\mymodule\EventSubscriber\SetExpiresSubscriber
    tags:
      - { name: event_subscriber }

2
Sie können den internen Seitencache mit \ Drupal :: service ('page_cache_kill_switch') -> trigger () deaktivieren. Wenn Ihr Block auf allen Seiten angezeigt wird, ist das natürlich irgendwie sinnlos.
Berdir

Ja, der page_kill_switch hat uns geholfen! Vielen Dank!
Gavz

@gavz Wenn Sie den Schalter verwenden, testen Sie mit curl --head, das max-ageist inCache-Control:
4k4

Sie können auch eine "RequestPolicyInterface" -Klasse verwenden, um das Caching gemäß einigen Parametern und der Anforderung zu verweigern. Weitere Informationen finden Sie unter api.drupal.org/api/drupal/… .
Renrhaf

Damit die Einstellungen der Leistungsseite den Ablauf des internen Seitencaches steuern können, könnte die onResponse()Methode des Dienstes in diesem Beispiel aktualisiert werden, um $page_max_age = \Drupal::config('system.performance')->get('cache.page.max_age');den Ablauf auf eine feste Anzahl von Sekunden in der Zukunft fest zu codieren, z. B. 3600.
David Lanier


1

Wenn der interne Seiten-Cache aktiviert sein muss (dh Sie können Varnish oder eine andere speicherbasierte Lösung nicht verwenden) und der interne Seiten-Cache lediglich die festgelegte Zeit einhalten soll admin/config/development/performance, können Sie Ihren eigenen Ereignis-Abonnenten hinzufügen, der den ändert FinishResponseSubscriber, den Drupal bereitstellt. Sie können sogar die Drupal-Konsole verwenden, um den größten Teil des Ereignisabonnenten für Sie zu generieren und dann die anderen Bits von FinishResponseSubscriber zu übernehmen. Ihr Ergebnis würde ungefähr so ​​aussehen:

/**
 * Class MyModuleSubscriber.
 *
 * @package Drupal\my_module
 */
class MyModuleSubscriber implements EventSubscriberInterface {

  /**
   * Sets extra headers on successful responses.
   *
   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
   *   The event to process.
   */
  public function onRespond(FilterResponseEvent $event) {
    if (!$event->isMasterRequest()) {
      return;
    }

    $request = $event->getRequest();
    $response = $event->getResponse();

    $this->setExpiresNoCache($response);

    return;

  }

  /**
   * Disable caching in ancient browsers and for HTTP/1.0 proxies and clients.
   *
   * HTTP/1.0 proxies do not support the Vary header, so prevent any caching by
   * sending an Expires date in the past. HTTP/1.1 clients ignore the Expires
   * header if a Cache-Control: max-age= directive is specified (see RFC 2616,
   * section 14.9.3).
   *
   * @param \Symfony\Component\HttpFoundation\Response $response
   *   A response object.
   */
  protected function setExpiresNoCache(Response $response) {
    $response->setExpires(REQUEST_TIME + 300);
  }

  /**
   * Registers the methods in this class that should be listeners.
   *
   * @return array
   *   An array of event listener definitions.
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('onRespond');
    return $events;

  }
}

Mit dem obigen Code wird die Cache-Lebensdauer auf 300 Sekunden fest codiert. Sie können jedoch stattdessen problemlos die Benutzereinstellung abrufen.


> "Sie können sogar Drupal Console verwenden, um den größten Teil des Event-Abonnenten für Sie zu generieren." Wofür brauche ich? Modul, Controller? Wo kann man diesen Codec einfügen?
Frank Giesecke

Hallo @FrankGiesecke, es gibt verschiedene Möglichkeiten, Drupal Console zu bekommen. Siehe drupalconsole.com
markfullmer

Hallo, die Konsole läuft jetzt. Welche Dateien brauche ich noch?
Frank Giesecke

0

Ich denke, Sie müssen das Modul 'Interner Seiten-Cache' deaktivieren, damit die Cache-Kontexte funktionieren.

Wenn "Interner Seiten-Cache" aktiviert ist, werden Inhalte für anonyme Benutzer standardmäßig zwischengespeichert.

Wenn Sie "Interner Seiten-Cache" deaktivieren, müssen Sie Drupal weiterhin anweisen, keinen Cache für anonyme Benutzer zu erstellen

$variables['#cache'] = [
  'contexts' => [
    // The "current user" is used above, which depends on the request,
    // so we tell Drupal to vary by the 'user' cache context.
    'user',
  ],
];

tut es für mich - ist aber wahrscheinlich nicht ganz richtig.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.