Date post: | 12-Apr-2017 |
Category: |
Technology |
Upload: | erik-stielstra |
View: | 1,094 times |
Download: | 0 times |
2
Cache it!Render cache in Drupal 8
3
About Wizzlern
Wizzlern
‣ 100% Drupal
‣ Drupal training and consultancy‣ Front-, backend-development ‣ Site administration and editorial‣ Advanced subjects
‣ Since 2009
‣ Active in the Drupal community
‣ Visit us at http://wizzlern.nl
4
5
Program
Drupal 8 Render Cache
‣ D7-D8 differences‣ Cache terminology‣ The thought process‣ Demonstration:
‣ Recent content list‣ Dynamic advertisement
6
Caching
7
“There are only two hard things in Computer Science:
cache invalidation and naming things.”
Phil Karlton
8
Drupal 7 - Page cache
‣ Core: Cache at page level.
‣ Low complexity cache invalidation.
‣ When a page is edited, the whole page cache is cleared.
‣ When a comment is added, the whole page cache is cleared.
9
Drupal 7 - Contrib cache
‣ Cache Expiration and various Varnish modules: High complexity cache invalidation:‣ purge / expire all URLs that contains the changing
content or is referring to it.‣ High invalidation costs.
10
Drupal 8 Render Cache
11
Drupal 8 strategy
‣ High-complexity cache invalidation
‣ Content invalidated instantaneously
‣ Cached permanently
‣ Cache chaining
‣ Rendered data cached at multiple levels:‣ Page, Block, Entity (node, comment, user, etc.),
View, Menu tree, Text Format filter result, etc.
12
Render #cache
13
$build['#cache'] = array( 'tags' => ['block_view', 'config:block.block.recentcontent'], 'contexts' => ['languages:language_interface', 'user.permissions'], 'max-age' => Cache::PERMANENT, );
Tags: Where the render result depends on.
Contexts: What makes the render result vary.
Max age: The max time the render result is valid.
For cache variations
To invalidate cache
Render #cache
‣ tags: Identifiers of rendered content. Used for cache invalidation.Example: node:42, user_view, config:image.style.large
‣ contexts: Contexts by which the content may vary.
‣ max-age: The maximum time cached content is valid. Defaults to permanent.
14
#cache context
‣ A string that refers to one of the available cache context services.‣ Examples:
‣ https://www.drupal.org/developing/api/8/cache/contexts
15
languages :typeroute .menu_active_trails :menu_name .namesessiontheme
timezoneuser .is_super_user .node_grants :operation .permissions .roles :role
Contexts may be hierarchical:parent.child
#cache tags
16
class AuthorNameFormatter extends FormatterBase {
public function viewElements(FieldItemListInterface $items) { $elements = array(); foreach ($items as $delta => $item) { /** @var $comment \Drupal\comment\CommentInterface */ $comment = $item->getEntity(); $account = $comment->getOwner(); $elements[$delta] = array( '#theme' => 'username', '#account' => $account, '#cache' => array( 'tags' => $account->getCacheTags() + $comment->getCacheTags(), ), ); } Cache tags for this render element.
Cache should respond to changes in account or comment.
Field formatter for comment author name.
#cache contexts, etc.
17
class CommentForm extends ContentEntityForm {
public function form(array $form, FormStateInterface $form_state) {
/** @var \Drupal\comment\CommentInterface $comment */ $comment = $this->entity; $entity = $this->entityManager->getStorage($comment->getCommentedEntityTypeId()) $field_name = $comment->getFieldName(); $field_definition = $this->entityManager->getFieldDefinitions($entity $config = $this->config('user.settings'); // In several places within this function, we vary $form on: // - The current user's permissions. // - Whether the current user is authenticated or anonymous. // - The 'user.settings' configuration. // - The comment field's definition. $form['#cache']['contexts'][] = 'user.permissions'; $form['#cache']['contexts'][] = 'user.roles:authenticated'; $this->renderer->addCacheableDependency($form, $config); $this->renderer->addCacheableDependency($form, $field_definition->getConfig($entity->bundle()));
Add cache contexts for users
The comment form depends on: - comment field settings- user settings
Add cache tags and contexts from the configuration this form depends on.
#cache: keys‣ #cache ‘keys’ are used for the database row ID.
‣ Most tags are created from ‘contexts’.‣ Some tags are added.
18
entity_view:block:bartik_main_menu:[languages:language_interface]=en:[languages:language_url]=en:[route.menu_active_trails:main]=menu_trail.main|:[theme]=bartik:[user.permissions]=120570f7a1954c488d57d2aac1dbc0a48b5072160533431c4ec9f19aa7602e86
#cache contexts:• languages:language_interface• languages:language_url• route.menu_active_trails:main• theme• user.permissions
Added keys:• entity_view• block• bartik_main_menu
Main menu block ‘cid’ taken from table cache_render
#cache bubbling
‣ Cacheability bubbles up during rendering.
‣ Child’s #cache properties are combined into the parent’s #cache properties.
‣ Helper functions in Renderer class.
19
Thought process
20
Am I rendering something? yes ['#cache']['contexts']
Does the output become outdated
after a certain time?
Does the output vary by
something?
Does the output depend on something?
['#cache']['tags']
['#cache']['max-age']
yes
yes
yes
Demo !
21
Demo: Recent content
A simple list of links to recent content.Repo: https://github.com/wizzlern/cacheit
22
Provided #cache data
‣ Content entities, configuration, block-, context-, condition-plugins, etc.
‣ Any objects that implement: CacheableDependencyInterface
23
interface CacheableDependencyInterface { public function getCacheContexts(); public function getCacheTags(); public function getCacheMaxAge(); }
Renderer::addCacheableDependency($build, $dependency)
Demo: Dynamic Ad
An advertisement block with dynamic content.Repo: https://github.com/wizzlern/cacheit
24
Placeholders
‣ Placeholders allow separation of cachable (‘static’) and non-cacheable (‘dynamic’) content.
‣ Lazy builder is a service.
‣ Builder arguments only integer, float, string, boolean.
25
if ($display->getComponent('links')) { $build[$id]['links'] = array( '#lazy_builder' => ['comment.lazy_builders:renderLinks', [ $entity->id(), $view_mode, $entity->language()->getId(), !empty($entity->in_preview), ]], '#create_placeholder' => TRUE, ); }
Placeholders
‣ Other placeholder data:‣ css, js header, js footer
‣ Auto placeholdering‣ When #cache properties are below a threshold‣ default: max-age: 0, contexts: ['session', ‘user']‣ Configuration:
renderer.config:auto_placeholder_conditions
26
Invalidation process
‣ Cache invalidation per tag‣ +1 ‘invalidation’ in cachetags table‣ Calculate the sum of invalidation of all tags.‣ Compare with ‘checksum’ value in cache_* table.
‣ Stale data remains in the cache_* table until overwritten by new data.
‣ See DatabaseCacheTagsChecksum class
27
Debugging
‣ Check cache metadata at page level:‣ http.response.debug_cacheability_headers : true
(in sites/*/services.yml)
‣ Check cache metadata at any level:‣ Renderviz module (still needs love)
‣ Database table cache_render
‣ Test with different user roles !!
28
Summary
29
Resources
‣ Classes:‣ Drupal\Core\Cache\Cache‣ Drupal\Core\Render\Renderer
‣ Documentation‣ https://drupal.org/developing/api/8/cache‣ http://drupal.org/developing/api/8/render/arrays/
cacheability
30
Links
‣ https://events.drupal.org/barcelona2015/sessions/making-drupal-fly-fastest-drupal-ever-here
‣ https://events.drupal.org/barcelona2015/sessions/caching-edge-cdns-everyone
31
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
32
http://wizzlern.nl@wizzlern