core/modules/system/theme.api.php | 60 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php index e555eef..cef7fd1 100644 --- a/core/modules/system/theme.api.php +++ b/core/modules/system/theme.api.php @@ -289,12 +289,13 @@ * * @section sec_cacheability Cacheability * - * Since the contents of a render array determine what is shown to the user, it - * also depends on render arrays "how cacheable" a page is. If your code is - * generating very dynamic render arrays (generally speaking, if it is using a - * lot of if-statements), then it also means that Drupal cannot simply cache the - * HTML that was rendered from your render array: it needs to call your code - * (and all those if-statements) when appropriate! + * Render arrays determine what is shown to the user. Therefore, arrays also + * determine how cacheable a response is. + * + * If code is generating very dynamic render arrays (generally speaking, if it + * is using a lot of if-statements), then that also means that Drupal cannot + * simply cache the HTML that was rendered from the render array: it needs to + * call the code (and all those if-statements) when appropriate. * * In other words: Drupal needs to be aware of how dynamic your code is. If it's * not aware, then it may send the same cached HTML to the wrong user! @@ -302,27 +303,30 @@ * This is why it is of the utmost importance that you inform the Render API of * the cacheability of a render array. * - * Whenever you are generating a render array, use the following 4 steps: - * 1. I'm rendering something. That means I must think of cacheability! + * Whenever you are generating a render array, use the following 5 steps: + * 1. I'm rendering something. That means I must think of cacheability. * 2. Is this something that's expensive to render, and therefore is worth * caching? If the answer is "yes", then what identifies this particular - * representation of the thing I'm rendering? - * Those are the cache keys. - * They're only necessary if I want to cache this render array. + * representation of the thing I'm rendering? Those are the cache keys. * 3. Does the representation of the thing I'm rendering vary per role (needs * permission), per URL (needs something of the request), per language, per … * something? Those are the cache contexts. - * They're always necessary, because they affect the cacheability of the - * entire page. Therefore they "bubble": parents automatically receive them. - * Note: cache contexts are completely analogous to HTTP's Vary header! + * Note: cache contexts are completely analogous to HTTP's Vary header. * 4. When does the representation of the thing I'm rendering become outdated? * I.e. which things does it depend upon, so that when those things change, - * so should my representation? - * Those are the cache tags. - * They're always necessary, because they affect the cacheability of the - * entire page. Therefore they "bubble": parents automatically receive them. + * so should my representation? Those are the cache tags. + * 5. When does the representation of the thing I'm rendering become outdated? + * I.e. is the data valid for a limited period of time only? + * That is the max-age (maximum age). It defaults to "permanently (forever) + * cacheable" (Cache::PERMANENT). When the representation is only valid for + * a limited time, set a max-age, expressed in seconds. Zero means that it's + * not cacheable at all. + * + * Cache contexts, tags and max-age must always be set, because they affect the + * cacheability of the entire response. Therefore they "bubble": parents + * automatically receive them. * - * Cache keys, contexts and tags together form the cache metadata trifecta. + * Cache keys must only be set if the render array should be cached. * * Let's apply this to a concrete example: * - cache keys: when rendering a node (thing) in the teaser view mode @@ -338,20 +342,14 @@ * any of them change, then the cached HTML for the node 5 teaser must be * regenerated. So my cache tags would be: ['node:5', 'user:3', 'file:4', * 'config:filter.format.basic_html']. + * - cache max-age: the node teaser remains valid until the node is changed, not + * for a limited time. So, there's no need to set a max-age: relying on the + * default (Cache::PERMANENT) will do. * * (Note: Drupal sets all the cache metadata in the above example automatically: * the entity view builder and field formatters take care of that. It's just * meant to be a concrete example that is intuitively understood by all.) * - * In summary: when a render array represents a thing, then: - * - cache keys identify a representation of a thing - * - may only be set if this render array should be cached - * - will trigger caching of this render array (subtree) - * - cache contexts identify the variations of the representation of the thing - * - must always be set (because they bubble & affect the entire page) - * - cache tags identify the dependencies of the representation - * - must always be set (because they bubble & affect the entire page). - * * Note that every Entity and Config has a ::getCacheTags() method, with which * one can easily get the cache tags of the objects a render array depends upon. * @@ -407,11 +405,11 @@ * @encode * * The generated markup is only slightly different, but the code became much - * simpler! It's logical though: the markup can now be used for all users, so - * less cacheability metadata is necessary. Most notably, no cache contexts are + * simpler. This is logical: the markup can now be used for all users, so less + * cacheability metadata is necessary. Most notably, no cache contexts are * present anymore (after all, there's only a single variation left now). * - * Finally: it is easy to see what cache contexts a certain page varies by and + * Finally: it is easy to see which cache contexts a certain page varies by and * which cache tags it is invalidated by: one must only look at the * X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags headers! *