Cache Repeated Hugo Template Work With partialCached

Hugo already builds most sites quickly, so caching every partial is unlikely to improve anything you can feel. It can also produce the wrong HTML when a cached partial depends on the current page.

partialCached is useful for a narrower problem: the same expensive partial produces the same output many times during one build.

A normal partial runs for every call

{{ partial "header.html" . }}

Hugo renders that partial each time it is called. For a small header or icon, that is simple and usually fast enough.

The cached form looks similar:

{{ partialCached "footer.html" . }}

Hugo can reuse the rendered result rather than repeating the work. The important question is not whether the partial can be cached. It is whether every call is allowed to receive the same output.

Site-wide output is the easy case

A social-links partial that reads one site configuration and renders the same list on every page is a reasonable candidate:

{{ partialCached "social-links.html" . }}

A breadcrumb partial is different. Its output depends on the page:

{{ partial "breadcrumbs.html" . }}

Caching it without another key may reuse one page’s breadcrumb on another page:

{{ partialCached "breadcrumbs.html" . }}

That is a fast build producing confidently wrong navigation. Not much of an optimization.

Variants make the cache page-aware

Extra arguments become cache variants. A path can separate breadcrumb output by page:

{{ partialCached
  "breadcrumbs.html"
  .
  .RelPermalink
}}

For navigation that changes by language, use the language as the variant:

{{ partialCached
  "navigation.html"
  .
  .Language.Lang
}}

The same idea works for a component type:

{{ partialCached
  "card.html"
  .
  .Params.type
}}

Every value that can change the rendered HTML must be represented in the cache variants. If the key grows into this:

{{ partialCached "thing.html" . .Title .Date .Type }}

I would stop and ask whether the saved build time is worth the extra reasoning.

Cache the work that appears in a profile

The best candidates tend to loop through large page collections, sort them, read data files, or build a site-wide index. A partial that prints one SVG is probably too cheap to matter.

Run a normal build first:

hugo

If the site finishes in 100 milliseconds, keep the normal partial. On a site with thousands of pages, profile the repeated work and cache the specific expensive output.

My default remains partial. I move to partialCached only when the output identity is clear and the build has repeated work worth removing. That keeps cache keys rare enough that their meaning stays obvious.