A long time ago @Leo_Merkel ask me a question in private. I feel making my answer public would benefit a lot of users here who struggle when choosing between the two.
.Render
vs partial
.Render
is a method of the page object. Its greatest advantage is template lookup order. It will use Hugo’s template lookup order to define which template file to use. So if you have two different title.html
template files, one for your entries of type post
and one for your entries of type page
each living in a directory named after those two types:
layouts/_default/title.html
layouts/post/title.html
layouts/page/title.html
Hugo would grab the type of the page .Render
is used on and find the right file for you. And if the file does not exist, gracefully fallback to your default file.
.Render
does not take any argument. The context passed to the template file is always the context of the page the method is used on.
partial
on the other hand is a global function. It can be used anywhere. It takes two arguments, the file path and the context to be passed to the template file.
It does not have any template lookout logic. So back to our title.html
example. You would have to place your two files in the layouts/partials
directory
layouts/partials/post/title.html
layouts/partials/page/title.html
And you would have to grab the page type and use it to build the partial’s path yourself prior to passing it to the partial
function and make sure the file exist or fall back to a default one. (Luckily there is templates.Exists
now).
So which one to use?
Now by those two definitions, it appears both have their pros and cons, but the limited context passed to the template file by .Render
will often be a problem for me. Unlike partial there is no way to conveniently complement or replace this default context.
For exemple, from within your partial you often need to know beyond the page context, like is this template file being used on a single page or a list page?
Let’s say you have a template file called article.html
to display your title, featured image and text.
The only difference in the file is calling .Summary
when in a list template vs .Content
when in a single template. A simple ternary condition could do!
Using .Render
though you would have no way to know if you’re supposed to call for .Summary
or .Content
, you’ve got nothing to test your condition on.
So in order to benefit form its amazing template lookup feature, you would have to create two quasi-identifcal html files, article_list.html
and article_single.html
(in each of your type directories) and replace the part dealing with .Summary
or .Content
.
This doesn’t seem much for many but it’s a no go for me. Having several identical template files and maintaining multiple files when changing the HTML of this section is a no go for me. (principles… ).
For these reasons, on my website which matches this use case, I had to fall back to using partial
. This way I’m able pass this information (list or single) to the context, and test my condition on it)
More
There is an ongoing issue to add the possibility to pass more to .Render
than the page context: Make the argument to .Render (optionally) be a map with type and layout keys · Issue #8182 · gohugoio/hugo · GitHub