Hey Hugo Folks,
tl;dr: In building layouts should we prefer multiple, per-section, not DRY templates over a single, DRY template with conditional logic?
Two years ago we welcomed a kid and in that intervening time I’ve been using Hugo to document his life, recipes, and occasional blogging and it’s Just Worked. Awesome. It met my needs and I’ve loved the stability. Thanks to all.
With a tiny bit more time on my hands, I decided to update the themes and my Hugo version etc. Catching up my layouts to align to incremental updates to my theme (ananke forever!) was kinda painful. So I decided to refactor my template logic.
In the mists of time, I had multiple sections that had their own /section.html
file. That’s been fine. But as I did a quick find(1), I had 8 of them, each with subtly different characteristics. So I pulled all the logic up into a single _default/section.html
with several conditionals inside and used the respective $SECTION/_index.md frontmatter to provide the conditional signals needed to render each section appropriately.
I tested this and everything works. Hooray Hugo.
But OH MY GOD, my build times went into the toilet.
| EN
-------------------+-------
Pages | 6239
Paginator pages | 399
Non-page files | 2615
Static files | 19
Processed images | 0
Aliases | 21
Cleaned | 0
Total in 122994 ms
versus the “multi-file” approach:
| EN
-------------------+-------
Pages | 6239
Paginator pages | 15
Non-page files | 2615
Static files | 19
Processed images | 0
Aliases | 16
Cleaned | 0
Total in 3910 ms
hugo 13.20s user 3.52s system 416% cpu 4.016 total
So the big leap here was in the number of pagination files. Let’s crank up the pagerSize config parameter.
| EN
-------------------+-------
Pages | 6239
Paginator pages | 95
Non-page files | 2615
Static files | 19
Processed images | 0
Aliases | 21
Cleaned | 0
Total in 30298 ms
hugo 44.62s user 5.58s system 165% cpu 30.407 total
OK, so clearly playing with pagination has a pretty big effect. OK, for each of those _index.md
files, let’s set pagination to off.
| EN
-------------------+-------
Pages | 6239
Paginator pages | 0
Non-page files | 2615
Static files | 19
Processed images | 0
Aliases | 20
Cleaned | 0
Total in 3892 ms
Aha. So, working hypothesis:
- Pagination is expensive
- It is more expensive when the lookup order (all the way up to
_default/list.html
) is “tall” - It is more expensive when that file has conditional logic
- Thus: Tradeoff is difficulty of maintenance of layout VERSUS speed/ability to paginate robustly
I sense a bit of “Yeah, well duh, when you paginate things get slower because we have to track more state, etc. – What did you expect?” here. If this performance is within tolerances. Great. I’ll paginate in smaller batches. But if this performance is outside the norm, I wanted to pass the data along.