У нас есть сайт, домашняя страница которого не кэшируется и содержит заголовки:
x-кеш: МИСС, МИСС
х-кэш-попаданий: 0, 0
x-content-type-options: nosniff
x-drupal-динамический-кеш: UNCACHEABLE
Я сузил это до содержимого областей контента и отключил «Контент главной страницы» для главной страницы. Затем это дало мне кеш HIT и больше не отвечало как UNCACHEABLE.Оттуда я сузил его до средства форматирования полей, используемого в абзаце. У нас есть пользовательский, который расширяет обычный форматировщик рендеринга объектов.
Если я поменяю его обратно на исходный форматтер «Render entity», все будет в порядке. Итак, это должно быть что-то, что мы делаем в этом пользовательском форматере, вызывающем проблему.
Когда я следую за xdebug, я вижу, что shouldCacheResponse из DynamicPageCacheSubscriber возвращает FALSE, потому что что-то устанавливает max-age в 0 (не по коду). Похоже, что вызовы addCacheableDependency могут вызывать такое поведение в форматере:
По сути, средство форматирования добавляет данные кеша в рендеринг, поэтому, если какой-либо из его элементов, на которые он ссылается, обновляется, кеш должен быть признан недействительным для этого абзаца хоста, чтобы он повторно рендерил:
$view_builder = \Drupal::entityTypeManager()->getViewBuilder($entity->getEntityTypeId());
$elements[$delta] = $view_builder->view($entity, $view_mode, $entity->language()->getId());
пытаться {
$parent = $items->getParent();
$parent_entity = $parent->getValue();
$elements[$delta]['#cache']['keys'][] = $parent_entity->id();
$elements[$delta]['#cache']['keys'][] = $parent_entity->bundle();
$elements[$delta]['#cache']['keys'][] = $parent_entity->getEntityTypeId();
$elements[$delta]['#cache']['keys'][] = 'delta_' . $ дельта;
$elements[$delta]['#cache']['keys'][] = 'context_aware';
$this->renderer->addCacheableDependency($elements[$delta], $parent);
если ($entity->hasField('field_author')) {
$child = $entity->field_author->entity;
если (isset($child)) {
$this->renderer->addCacheableDependency($elements[$delta], $child);
}
}
// аналогичные операторы с addCacheableDependency
Если я прокомментирую эту начальную строку:
$this->renderer->addCacheableDependency($elements[$delta], $parent);
Затем я получаю кешируемый ответ.Похоже, это связано с тем, что элемент $parent (даже если это узел, абзац или медиаобъект) вызывает это:
/**
* Создает объект CacheableMetadata из зависимого объекта.
*
* @param \Drupal\Core\Cache\CacheableDependencyInterface|смешанный объект $
* Объект, метаданные кэшируемости которого необходимо получить. Если он реализует
* CacheableDependencyInterface, будут использоваться его метаданные кешируемости,
* в противном случае переданный объект должен считаться некэшируемым, поэтому
* установлен максимальный возраст 0.
*
* @return статический
*/
общедоступная статическая функция createFromObject($object) {
if ($object instanceof CacheableDependencyInterface) {
$мета = новый статический();
$meta->cacheContexts = $object->getCacheContexts();
$meta->cacheTags = $object->getCacheTags();
$meta->cacheMaxAge = $object->getCacheMaxAge();
вернуть $мета;
}
// Объекты, которые не реализуют CacheableDependencyInterface, должны считаться
// быть некэшируемым, поэтому установите max-age 0.
$мета = новый статический();
$meta->cacheMaxAge = 0;
вернуть $мета;
}
Установка для cacheMaxAge значения 0, поскольку это не экземпляр CacheableDependencyInterface.
Если я уже устанавливаю ключи кеша, нужна ли эта строка:
$this->renderer->addCacheableDependency($elements[$delta], $parent);
Если я уберу это, будет ли неблагоприятный эффект (например, рендеринг не будет выполнять повторный рендеринг при сохранении ссылочных элементов)?