Set variable globally for bundling CSS?

Hi, I am new to Hugo, so bear with me.

I am currently including multiple CSS assets in the < head > of my baseof.html.
I do this by using partial templates, and using a block inserted into the head for each separate page’s CSS.
This flow is working fine, but results it many CSS files being loaded in the browser.

I would like to try bundling the CSS to reduce website load time.

Is there a global variable that I can accumulate these CSS assets into, and then bundle them together in baseof.html?

For instance, in multiple partial templates, I would have:
$.cssBundle := slice $.cssBundle $asset
Then in baseof to generate a bundle file:
$.cssBundle := $.cssBundle | resources.Concat "bundle.css"
Then include the bundle with a < link > tag

Is something like this possible? Is it required that I have all my CSS file reference variables in one place when I create the bundle?

Is it possible to do this by using:
.Scratch.Set
within each of my partials, and accessing in baseof.html with:
.Scratch.Get

?

Yes, but you need to carefully consider the “order of” things, e.g. baseof:

{{ block "css-init" . }}each single.html, list.html etc. needs to add their CSS in here{{ end }}
{{ $files := .Scratch.Get "css-files" }}}

Or something.

Thanks for the response, Bep!

Would I be able to accumulate filenames into a slice with
.Scratch.Set
from various locations (various partial templates)?

Would I do this each time for every CSS ‘include’ portion?

Depends. Those partials needs to be invoked before the concatenation, so to speak.

Ah, got it.
I suppose my question would be:
Is it possible to append items to a slice (defined in .Scratch.Set) from multiple different locations (like within each partial template)?

Thanks for the support thus far Bep

Jumping in to say: yes, you can do this.

Not the same use case, but a while back I was playing with the idea of debugging partials and layouts by constructing a tree of all the partials that get called to render a specific page.

The basic idea is, for example in my baseof:

    {{ .Scratch.Add "trace" (slice "<baseof>") }}
    {{- partial "head.html" . -}}
    <body>
        {{- partial "header.html" . -}}
        {{- block "main" . }}{{- end }}
        {{- partial "footer.html" . -}}
    </body>
    {{ .Scratch.Add "trace" "</baseof>" }}
    {{ .Scratch.Get "trace" }}

and then in each layout file and partial i would have:

{{ .Scratch.Add "trace" "<footer.html>" }}
<!-- actual layout stuff here -->
{{ .Scratch.Add "trace" "</footer.html>" }}

So that when I do a {{ .Scratch.Get "trace" }} I get:

[
<baseof>
<head.html>
<head/css.html>
</head/css.html>
<head/meta.html>
</head/meta.html>
</head.html>
<header.html>
</header.html>
<layouts/index.html>
<utils/foo.html>
</utils/foo.html>
<utils/bar.html>
</utils/bar.html>
</layouts/index.html>
<footer.html>
</footer.html>
</baseof>
]

Note that his only works because I am calling .Scratch.Get at the very end. The order is important.

As bep said above, the partials need to have been invoked before. So if you try to .Scratch.Get before the relevant partial has been rendered, it will not have the information from that partial.

So in my example, if you wanted to append your css classes to the <body> tag, your .Scratch would only have the tags up to </head.html> because the rest have not rendered yet.

1 Like

Thanks for the response, Pointyfar!

I have tried the following (below) with no luck. Let me know if you can give me any insight.
In the meantime, I should mention that I have a workaround for my issue.

layouts/index.html:
Defines main block.
Within main block, I include multiple partial templates to construct my homepage.

layouts/_default/baseof.html:
Specifies my overall HTML template.
This file places the main block within the body tag.

layouts/partials/services/single.html:
This partial is included in layouts/index.html within the main block definition.
Within this partial, I define a single CSS file I want to add to the total bundle (CSS only related to this partial).
In this file, I specify {{ .Scratch.Add "cssBundle" "/css/services/single.css" }}.
In layouts/_default/baseof.html I am unable to access this scratch variable whether I access before the main block, or after.
I access with {{ .Scratch.Get "cssBundle }}.

Should I be able to access this Scratch variable within baseof.html?
Say I was able to access this Scratch variable within baseof.html:
Would I be able to use the Scratch variable within <head> in baseof.html?
This would involve using the variable within <head> before the main block is used, as <head> is before <body> - where the main block is included.

Just to clarify, I am trying associate a CSS file with each individual partial. Then when I use all my partials for my homepage, I want to bundle all the CSS files together.

Thanks!

It would be easier to help you if you had your code somewhere we can have a look at instead of just theoretical snippets.

Have a read at the docs here: https://gohugo.io/functions/scratch/

You should be able to access the .Scratch from the baseof, with the conditions discussed above.

That’s what we mean above, when we say the order matters.

  {{ .Scratch.Get "foo" }} => ""

1 {{ .Scratch.Add "foo" (slice "A") }}
2 {{ .Scratch.Get "foo" }} => [A] 
3 
4 {{ .Scratch.Add "foo" "B" }}
5 {{ .Scratch.Get "foo" }} => [A B] 
6 
7 {{ .Scratch.Add "foo" "C" }}
8 {{ .Scratch.Get "foo" }} => [A B C] 

So if your main block gets defined at line 3, but you are doing a .Scratch.Get at line 2, then it would only have a value of [A].

Thanks Pointyfar.
I may upload my code at some point. I will let you know if I do.
It seems that when I set a Scratch variable from within the partial HTML file, this same variable is not “Get-able” from the baseof.html. Is that expected behavior?
Again, thank you everyone for the help thus far.