I think both of them are functions that copy code from other files to the working file. So what is the difference? And when should I use .Render
(or partial
)?
Two previous threads:
Ops, sorry, I didn’t see it early. My bad.
I had the same question and asked @regis about that. Here’s his great answer and explanation:
.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 fell back to using partial
. This way I’m able pass this information (list or single) to the context, and test my condition on it)
Oh and an issue…
Also, while using Custom Output format, I found that .Render
only look for files matching the main Output Format rather than the current one (#5090).
So here again, when dealing with Output Formats, I had to fall back to partial
and do the template lookup and file exist check myself.
This will, among other similar known limitations, be fixed in Hugo 0.55.
.Render
is (now) documented to offer greatest advantage in list template, where you might be most likely to loop through potentially different types of pages. I’d offer another scenario, where you want to show page snippets in search results (which also loop through a bunch of potentially different types of pages). So it’s no longer positioned as a general purpose alternative to partial.
But you could mimic any collection of view templates with a single partial with an N-way test on page type, section or kind.
The one place where .Render
has a clear advantage is in modularity. Suppose you’re writing a theme and you expect others to write plugins for new page types. If your theme had a partial with the N-way test, you’d have to add a case to handle the plugin. But if you use .Render
, plugin writer simply writes an additional view template of the right name and it all just works.
So I think it’s an elegant solution to a relatively rare problem, FWIW.