Optimizing Hugo

PUBLISHED ON 03/04/2020 — EDITED ON 06/04/2020 — DEVELOPMENT

Intro

As Hugo is regarded as ultimate speed machine, I wanted to see how far can I push it.

We can see here the “before” speed tests were ok, but there was a bit of room for improvement.

Before Before

Combine and minify asset files

CSS

The test shows 7 different CSS requests, not a lot, but too much. Fortunately Hugo has integrated functions to combine multiple CSS files (slice) and minify them, so instead of loading multiple smaller files, browser can be provided with one big one.

So to use both options, I have edited header.html file:

{{ $csszenburn := resources.Get "/css/zenburn.min.css" }}
{{ $cssfonts := resources.Get "/css/fonts.css" }}
{{ $cssbootstrap := resources.Get "/css/bootstrap-v3.3.7/bootstrap.min.css" }}
{{ $cssfontawesome := resources.Get "/css/fontawesome-v5.12.0/all.css" }}
{{ $cssmain := resources.Get "/css/main.css" }}
{{ $csscustom := resources.Get "/css/custom.css" }}
{{ $cssfull := slice $csszenburn $cssfonts $cssbootstrap $cssfontawesome $cssmain $csscustom | resources.Concat "/css/bundle.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $cssfull.Permalink }}" integrity="{{ $cssfull.Data.Integrity }}">

JavaScript

The same thing can be done with JavaScript. I load the scripts in footer, so page load feels quicker. Edit footer.html:

{{ $csssyntax := resources.Get "/css/syntax.css" }}
{{ $cssfonts := resources.Get "/css/fonts.css" }}
{{ $cssbootstrap := resources.Get "/css/bootstrap-v3.3.7/bootstrap.min.css" }}
{{ $cssmain := resources.Get "/css/main.css" }}
{{ $csscustom := resources.Get "/css/custom.css" }}
{{ $cssfull := slice $csssyntax $cssfonts $cssbootstrap $cssmain $csscustom | resources.Concat "/css/bundle.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $cssfull.Permalink }}" integrity="{{ $cssfull.Data.Integrity }}">

In the same take, I have ditched highlightjs for integrated syntax highlighter:

$ hugo gen chromastyles --style=monokai > syntax.css

HTML

We can minify HTML files by using --minify parameter while using hugo:

$ hugo --minify

Local Google fonts

https://google-webfonts-helper.herokuapp.com/fonts/roboto?subsets=latin

Ditching Fontawesome for feathericons

Define your chosen icons, simply pick and download SVG files from feathericons.com and copy the data.

$ cat layouts/partials/svg/icons.html
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#526d7a" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
    {{ if eq "prev" . }}
    	<line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline>
    {{ else if eq "next" . }}
    	<line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline>
	{{ else if eq "mail" . }}
    	<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline>
    {{ else if eq "github" . }}
    	<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
    {{ else if eq "twitter" . }}
    	<path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path>
    {{ else if eq "linkedin" . }}
    <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle>
    {{ else if eq "rss" . }}
    	<path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle>
   	{{ else if eq "home" . }}
        <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline>
	{{ else if eq "menu" . }}
		<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>
	{{ else if eq "key" . }}
		<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"></path>
    {{ end }}
  </svg>

Usage:

<section id="menu-pane" class="row menu text-center">
  {{ if not .IsNode }}
  {{ with .PrevInSection }}
  <span><a class="menu-item" href="{{ .Permalink }}">{{ partial "svg/icons" "prev" }}</a></span>
  {{ end }}
  {{ if (or (.PrevInSection) (.NextInSection)) }}
  <!--- <span><a class="menu-item" href="{{ .Section | relURL }}">{{ .Section | lower }}</a></span> -->
  <span><a class="menu-item" href="{{ .Section | relURL }}">{{ partial "svg/icons" "menu" }}</a></span>
  {{ end }}
  {{ with .NextInSection }}
  <span><a class="menu-item" href="{{ .Permalink }}">{{ partial "svg/icons" "next" }}</a></span>
  {{ end }}
  {{ end }}
  <h4 class="text-center"><a class="menu-item" href="{{ .Site.BaseURL }}">{{ partial "svg/icons" "home" }}</a></h4>
</section>

Results and epilogue

After After

See Also