2024-04-19 11:38:03 +01:00
|
|
|
---
|
|
|
|
title: Wagtail & Caching
|
|
|
|
class: text-center
|
|
|
|
highlighter: shiki
|
|
|
|
transition: slide-left
|
2024-05-03 13:33:41 +01:00
|
|
|
monaco: false
|
2024-04-19 11:38:03 +01:00
|
|
|
mdc: true
|
|
|
|
themeConfig:
|
|
|
|
primary: '#2e1f5e'
|
|
|
|
---
|
|
|
|
|
|
|
|
# Wagtail & Caching
|
|
|
|
|
|
|
|
### Jake Howard{style="color: #e85537;" }
|
|
|
|
|
|
|
|
<ul class="list-none! text-sm [&>li]:m-0! mt-1 uppercase">
|
|
|
|
<li><em>Senior Systems Engineer</em> @ Torchbox <mdi-fire class="fill-white"/></li>
|
|
|
|
<li><em>Security Team</em> & <em>Performance Working Group</em> @ Wagtail <logos-wagtail class="fill-white"/></li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<ul class="list-none! text-xs [&>li]:m-0! mt-3 font-light">
|
|
|
|
<li><mdi-earth /> theorangeone.net</li>
|
|
|
|
<li><mdi-twitter /> @RealOrangeOne</li>
|
|
|
|
<li><mdi-github /> @RealOrangeOne</li>
|
|
|
|
<li><mdi-mastodon /> @jake@theorangeone.net</li>
|
|
|
|
</ul>
|
2024-04-19 17:46:32 +01:00
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
# Disclaimer{style="color: #fd5765;" }
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
---
|
|
|
|
|
|
|
|
# What _is_ caching?
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: center
|
|
|
|
---
|
|
|
|
|
2024-05-03 13:33:41 +01:00
|
|
|
|
|
|
|
# Scale
|
|
|
|
|
|
|
|
<style>
|
|
|
|
@keyframes grow {
|
|
|
|
from {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
to {
|
|
|
|
font-size: 30rem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
h1 {
|
|
|
|
animation-name: grow;
|
|
|
|
animation-duration: 30s;
|
|
|
|
animation-timing-function: linear;
|
|
|
|
animation-fill-mode: forwards;
|
|
|
|
}
|
|
|
|
|
|
|
|
</style>
|
2024-04-19 17:46:32 +01:00
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
---
|
|
|
|
|
2024-05-03 13:33:41 +01:00
|
|
|
# <logos-wagtail class="fill-white"/> Caching <em>in Wagtail</em>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: section
|
|
|
|
---
|
|
|
|
|
|
|
|
## 1:
|
|
|
|
# Template Fragment Caching
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: https://d1nvwtjgmbo5v5.cloudfront.net/media/images/Screen_Shot_2015-05-14_at_09.01.5.2e16d0ba.fill-1200x996.png
|
|
|
|
backgroundSize: cover
|
|
|
|
---
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.slidev-layout {
|
|
|
|
background-position: top center !important;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: none
|
|
|
|
---
|
|
|
|
|
|
|
|
```html
|
|
|
|
<div class="one-half--medium one-third--large">
|
|
|
|
<div class="card card--link">
|
|
|
|
<a href="/developers/springload/made-wagtail/" class="project-image">
|
|
|
|
<img src="https://d1nvwtjgmbo5v5.cloudfront.net/media/images/Screen_Shot_2015-05-14_at_09.01.52.2e16d0ba.fill-680x564.png" alt="" title="">
|
|
|
|
</a>
|
|
|
|
<div class="project__links">
|
|
|
|
<a class="project__info" href="/developers/springload/made-wagtail/">
|
|
|
|
<span class="u-sr-only">Project info</span>
|
|
|
|
<svg class="i i--grey i--hover">
|
|
|
|
<use xlink:href="#i-info"></use>
|
|
|
|
</svg>
|
|
|
|
</a>
|
|
|
|
<a class="project__visit" href="http://madewithwagtail.org/" title="Project link" data-analytics="Project|Link click">
|
|
|
|
<span class="u-sr-only">Project link</span>
|
|
|
|
<svg class="i i--grey i--hover">
|
|
|
|
<use xlink:href="#i-visit"></use>
|
|
|
|
</svg>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<h4 class="project-title">
|
|
|
|
Made with Wagtail
|
|
|
|
</h4>
|
|
|
|
<p class="project-author">
|
|
|
|
<a href="/developers/springload/" title="View the company page of Springload">
|
|
|
|
Springload
|
|
|
|
</a>
|
|
|
|
</p>
|
|
|
|
```
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.slidev-page, .slidev-code-wrapper, .slidev-code {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
2024-04-19 17:46:32 +01:00
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
2024-05-03 13:33:41 +01:00
|
|
|
background: /website-homepage.png
|
2024-04-19 17:46:32 +01:00
|
|
|
---
|
|
|
|
|
2024-05-03 13:33:41 +01:00
|
|
|
# An example
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: /website-posts.png
|
|
|
|
---
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: none
|
|
|
|
---
|
|
|
|
|
|
|
|
````md magic-move
|
|
|
|
```html
|
|
|
|
{% load wagtailcore_tags util_tags %}
|
|
|
|
|
|
|
|
<article class="media listing-item">
|
|
|
|
<div class="columns">
|
|
|
|
<figure class="media-left column is-{{ show_listing_images|yesno:'3,1' }} image-column">
|
|
|
|
{% if page.list_image_url %}
|
|
|
|
<a href="{% pageurl page %}" class="image" title="{{ page.title }}">
|
|
|
|
<img src="{{ page.list_image_url }}" alt="{{ page.hero_image_alt }}" loading="lazy" decoding="async" referrerpolicy="no-referrer" />
|
|
|
|
</a>
|
|
|
|
{% endif %}
|
|
|
|
</figure>
|
|
|
|
<div class="media-content column">
|
|
|
|
<div>
|
|
|
|
{% if breadcrumbs %}
|
|
|
|
{% include "common/breadcrumbs.html" with parents=page.get_parent_pages %}
|
|
|
|
{% endif %}
|
|
|
|
<h2 class="title is-3">
|
|
|
|
<a href="{% pageurl page %}">{{ page.title }}</a>
|
|
|
|
</h2>
|
|
|
|
{% include "common/content-details.html" %}
|
|
|
|
<p>{{ page.summary }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article>
|
|
|
|
```
|
|
|
|
|
|
|
|
```html {all|1|3,27|4-26|all}
|
|
|
|
{% load wagtailcore_tags wagtail_cache util_tags %}
|
|
|
|
|
|
|
|
{% wagtailpagecache FRAGMENT_CACHE_TTL "listing-item" breadcrumbs show_listing_images %}
|
|
|
|
<article class="media listing-item">
|
|
|
|
<div class="columns">
|
|
|
|
<figure class="media-left column is-{{ show_listing_images|yesno:'3,1' }} image-column">
|
|
|
|
{% if page.list_image_url %}
|
|
|
|
<a href="{% pageurl page %}" class="image" title="{{ page.title }}">
|
|
|
|
<img src="{{ page.list_image_url }}" alt="{{ page.hero_image_alt }}" loading="lazy" decoding="async" referrerpolicy="no-referrer" />
|
|
|
|
</a>
|
|
|
|
{% endif %}
|
|
|
|
</figure>
|
|
|
|
<div class="media-content column">
|
|
|
|
<div>
|
|
|
|
{% if breadcrumbs %}
|
|
|
|
{% include "common/breadcrumbs.html" with parents=page.get_parent_pages %}
|
|
|
|
{% endif %}
|
|
|
|
<h2 class="title is-3">
|
|
|
|
<a href="{% pageurl page %}">{{ page.title }}</a>
|
|
|
|
</h2>
|
|
|
|
{% include "common/content-details.html" %}
|
|
|
|
<p>{{ page.summary }}</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</article>
|
|
|
|
{% endwagtailpagecache %}
|
|
|
|
```
|
|
|
|
````
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.slidev-page, .slidev-code-wrapper, .slidev-code {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
background: /website-search.png
|
|
|
|
---
|
|
|
|
|
|
|
|
# Duplication
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: center
|
|
|
|
---
|
|
|
|
|
|
|
|
```html {3}
|
|
|
|
<section class="container">
|
|
|
|
{% for page in listing_pages %}
|
|
|
|
{% include "common/listing-item.html" %}
|
|
|
|
{% endfor %}
|
|
|
|
</section>
|
|
|
|
```
|
|
|
|
|
|
|
|
<style>
|
|
|
|
code {
|
|
|
|
font-size: 1.5rem !important;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: /website-search.png
|
|
|
|
---
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
# Cache invalidation
|
|
|
|
|
|
|
|
<v-click>
|
|
|
|
|
|
|
|
```python
|
|
|
|
>>> BlogPostPage.objects.first().cache_key
|
|
|
|
```
|
|
|
|
|
|
|
|
</v-click>
|
|
|
|
|
|
|
|
<v-click>
|
|
|
|
|
|
|
|
```python
|
|
|
|
@property
|
|
|
|
def cache_key(self) -> str:
|
|
|
|
"""
|
|
|
|
A generic cache key to identify a page in its current state.
|
|
|
|
Should the page change, so will the key.
|
|
|
|
|
|
|
|
Customizations to the cache key should be made in :attr:`get_cache_key_components`.
|
|
|
|
"""
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
</v-click>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
code {
|
|
|
|
font-size: 1rem !important;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: center
|
|
|
|
---
|
|
|
|
|
|
|
|
# What about Django?
|
|
|
|
|
|
|
|
```jinja
|
|
|
|
{% load cache %}
|
|
|
|
{% cache 500 sidebar request.user.username %}
|
|
|
|
.. sidebar for logged in user ..
|
|
|
|
{% endcache %}
|
|
|
|
```
|
|
|
|
<Transform :scale="1.4">
|
|
|
|
<v-clicks>
|
|
|
|
|
|
|
|
- Current page
|
|
|
|
- Current site
|
|
|
|
- Preview
|
|
|
|
- Cache invalidation
|
|
|
|
|
|
|
|
</v-clicks>
|
|
|
|
</Transform>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
code {
|
|
|
|
font-size: 1.5rem !important;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: section
|
|
|
|
---
|
|
|
|
|
|
|
|
## 2:
|
|
|
|
# Frontend Caching
|
2024-05-03 17:47:51 +01:00
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
U[User]
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U--->CDN
|
|
|
|
CDN-..->W
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart TD
|
|
|
|
U1[🧑💻]
|
|
|
|
U2[🧑💻]
|
|
|
|
U3[🧑💻]
|
|
|
|
U4[🧑💻]
|
|
|
|
U5[🧑💻]
|
|
|
|
U6[🧑💻]
|
|
|
|
U7[🧑💻]
|
|
|
|
U8[🧑💻]
|
|
|
|
U9[🧑💻]
|
|
|
|
U10[🧑💻]
|
|
|
|
U11[🧑💻]
|
|
|
|
U12[🧑💻]
|
|
|
|
U13[🧑💻]
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U1--->CDN
|
|
|
|
U2--->CDN
|
|
|
|
U3--->CDN
|
|
|
|
U4--->CDN
|
|
|
|
U5--->CDN
|
|
|
|
U6--->CDN
|
|
|
|
U7--->CDN
|
|
|
|
U8--->CDN
|
|
|
|
U9--->CDN
|
|
|
|
U10--->CDN
|
|
|
|
U11--->CDN
|
|
|
|
U12--->CDN
|
|
|
|
U13--->CDN
|
|
|
|
CDN-...->W
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: https://www.cloudflare.com/network-maps/cloudflare-pops-2O04nulSdNrRpJR9fs9OKv.svg
|
|
|
|
---
|
|
|
|
|
|
|
|
Source: Cloudflare
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.slidev-layout {
|
|
|
|
background: white;
|
|
|
|
}
|
|
|
|
|
|
|
|
p {
|
|
|
|
color: black;
|
|
|
|
position: absolute;
|
|
|
|
bottom: 0;
|
|
|
|
font-size: 0.66rem;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
background: /wagtail-homepage.png
|
|
|
|
---
|
|
|
|
|
|
|
|
# An example
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: /map.jpg
|
|
|
|
transition: fade
|
|
|
|
---
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
background: /map.jpg
|
|
|
|
---
|
|
|
|
|
|
|
|
# ~XXms
|
|
|
|
|
|
|
|
<style>
|
|
|
|
h1 {
|
|
|
|
font-size: 4rem;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
U[User]
|
|
|
|
|
|
|
|
subgraph Content Delivery Network
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
C[(Cache)]
|
|
|
|
end
|
|
|
|
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U---->CDN
|
|
|
|
CDN-.->C
|
|
|
|
C---->W
|
|
|
|
C-.->CDN
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
U[User]
|
|
|
|
A[Admin]
|
|
|
|
|
|
|
|
subgraph Content Delivery Network
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
C[(Cache)]
|
|
|
|
end
|
|
|
|
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U---->CDN
|
|
|
|
CDN-.->C
|
|
|
|
C---->W
|
|
|
|
C-.->CDN
|
|
|
|
|
|
|
|
A---->CDN
|
|
|
|
CDN---->W
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
# Content is cached!
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
U1[User]
|
|
|
|
U2[User]
|
|
|
|
U3[User]
|
|
|
|
|
|
|
|
subgraph Content Delivery Network
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
C[(Cache)]
|
|
|
|
end
|
|
|
|
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U1===>CDN
|
|
|
|
U2===>CDN
|
|
|
|
U3===>CDN
|
|
|
|
CDN==>C
|
|
|
|
C==>CDN
|
|
|
|
C-.....->W
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: image
|
|
|
|
image: /wagtail-homepage-typo.png
|
|
|
|
---
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: section
|
|
|
|
---
|
|
|
|
|
|
|
|
## Solution:
|
|
|
|
# Frontend Cache Invalidation
|
|
|
|
### Wagtail secret sauce <logos-wagtail class="fill-white"/>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
U[User]
|
|
|
|
|
|
|
|
subgraph Content Delivery Network
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
C[(Cache)]
|
|
|
|
end
|
|
|
|
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
U--->CDN
|
|
|
|
CDN-->C
|
|
|
|
C-->CDN
|
|
|
|
C-..->W
|
|
|
|
|
|
|
|
W-.->|Frontend Cache Invalidation|CDN
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: center
|
|
|
|
---
|
|
|
|
|
|
|
|
# `settings.py`
|
|
|
|
|
|
|
|
### 1.
|
|
|
|
|
|
|
|
```python {3}
|
|
|
|
INSTALLED_APPS = [
|
|
|
|
...
|
|
|
|
"wagtail.contrib.frontend_cache"
|
|
|
|
]
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 2.
|
|
|
|
|
|
|
|
```python
|
|
|
|
WAGTAILFRONTENDCACHE = {
|
|
|
|
'cloudflare': {
|
|
|
|
'BACKEND': 'wagtail.contrib.frontend_cache.backends.CloudflareBackend',
|
|
|
|
'BEARER_TOKEN': os.environ["CF_BEARER_TOKEN"],
|
|
|
|
'ZONEID': os.environ["CF_ZONE_ID"],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### 3. ???
|
|
|
|
|
|
|
|
#### 4. Profit!
|
|
|
|
|
|
|
|
<style>
|
|
|
|
code {
|
|
|
|
font-size: 0.9rem !important;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: fact
|
|
|
|
---
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
flowchart LR
|
|
|
|
A[Admin]
|
|
|
|
|
|
|
|
subgraph Content Delivery Network
|
|
|
|
CDN{Content<br>Delivery Network}
|
|
|
|
C[(Cache)]
|
|
|
|
end
|
|
|
|
|
|
|
|
W[(Wagtail)]
|
|
|
|
|
|
|
|
A-->|Publish new content to<br><code>/blog/post-1</code>|W
|
|
|
|
|
|
|
|
W-.->|<code>PURGE /blog/post-1</code>|CDN
|
|
|
|
|
|
|
|
CDN-.->C
|
|
|
|
```
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
background: https://d1nvwtjgmbo5v5.cloudfront.net/media/images/Screen_Shot_2015-05-14_at_09.01.5.2e16d0ba.fill-1200x996.png
|
|
|
|
---
|
|
|
|
|
|
|
|
# Conclusion
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: cover
|
|
|
|
---
|
|
|
|
|
|
|
|
<Transform :scale="1.3">
|
|
|
|
|
|
|
|
# Performance means:
|
|
|
|
|
|
|
|
|
|
|
|
- Users are happier <mdi-emoticon-happy />
|
|
|
|
- Servers are happier <mdi-server-network />
|
|
|
|
- The planet is happier <mdi-earth class="text-green" />
|
|
|
|
|
|
|
|
</Transform>
|
|
|
|
|
|
|
|
---
|
|
|
|
layout: end
|
|
|
|
---
|