Caching Large Navigation Menus in Drupal

Benji Fisher

March 10, 2019

Before We Get Started

Push the Big, Red Button!

Big, red button 

Blog post

https://www.isovera.com/blog/caching-large-navigation-menus-drupal

Introduction

About Me

Yellow Pig 

About Isovera

Isovera 

https://www.isovera.com/

  • Strategy
  • Design
  • Development
  • Training

Book Navigation Needs To Be Cached

Pega Community Doc Page

Book navigation is nested several levels
Book navigation is nested several levels

Numbers

  • 4472 pages in the book
  • 2.7 MB rendered (twice) for each page
  • 40-50 sec initial load
  • 6-9 sec load after caching

After I did this work, the cached page loads in 2-3 sec.

Strategy

  1. Use the same navigation on all pages
  2. Set active trail with javascript
  3. Cache the navigation once per book

Internal vs. External Cache

Drupal FTW

Caching is one of the strengths of Drupal 8.

Logo for Drupal 8 

Internal Cache

Drupal stores bits and pieces in database or memcache or redis.

Diagram showing database on the left, Drupal on the right 

External Cache

Whole pages are stored in the database, Varnish, or a CDN.

Diagram showing Drupal, database, browser 

The Hard Part

For both internal and external caches, the hard part is knowing when to clear the cache.

Two hard things

  1. Naming things
  2. Off-by-one errors
  3. Cache invalidation

Twig Template

Twig Template (simplified)

{% if tree %}
  <nav class="c-book-nav" role="navigation" aria-labelledby="book-label-{{ book_id }}">
    <a href="{{ book_url }}">
      {{ top_book_title }}
    </a>
    {{ tree }}
  </nav>
{% endif %}

Twig Template (full)

{% if tree %}
  <nav class="c-book-nav" role="navigation" aria-labelledby="book-label-{{ book_id }}">
    {% if top_book_title %}
      {% if not top_book_empty %}
        <a href="{{ book_url }}">
      {% endif %}
        {{ top_book_title }}
      {% if not top_book_empty %}
        </a>
      {% endif %}
    {% endif %}
    {{ tree }}
  </nav>
{% endif %}

Drupal Code

Hook Node View

Hook Theme

Preprocess Function

Javascript

Hook Node View (review)

Hook Node View

Cache Keys

  • A unique string to identify “our” cache
  • The book ID

This is how we cache once per book.

Without cache keys, any cache data will bubble up.

Cache Contexts

If the book is viewed in another language, then the link text will change.

Maybe also the link URLs.

This site is not (yet) multilingual.

Cache Tags

These are saved in the database.

When node/$book_id is updated, delete from the cache.

At page level, cache tags are sent in HTTP headers. Varnish/CDN invalidates based on cache tags.

Cache Max Age

Keep the cached version until I say to clear it.

Peek At the Database

The cache_render Table

Query

Cache ID

  • We specified pdn_book_nav in the cache keys
  • The book ID also comes from cache keys
  • languages comes from cache contexts
  • theme and permissions … see below

Cache Max Age

Cache Tags

Permissions Hash

Where do permissions come from?

See sites/default/services.yml:

After Party

Questions

Feedback

https://nerd.ngo/feedback

Screenshot of feedback form
Screenshot of feedback form

Copyleft

Creative Commons License
This slide deck by Benji Fisher is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at https://gitlab.com/benjifisher/slide-decks.