Hugo

Generating Just A Single JavaScript File

Hi,

in my project, different pages require different pieces of JavaScript code depending on e.g. which short codes are used. I was looking for a way to

  1. Only include the JavaScript code which is actually required for a page
  2. Only use a single HTTP request per page for JavaScript

To solve this, I developed a little technique which I wanted to share - maybe somebody can reuse (or improve on) it. :slight_smile:

The general idea is that all layouts can ‘register’ a script for inclusion - the baseof.html template then takes care of generating a single resource.

The central pieces are two partial layouts:

  1. layouts/partial/resources/register_script.html: this partial can be called to register a script. It’s just an abstraction over the scratch pad and contains just

     {{ .scratch.Add "scripts" .resource }}
    
  2. layouts/partial/resources/combine.html: this partial is invoked by baseof.html and takes care of combining all registered resources. It concatenates all resources (alas, ‘resource.Combine’ wouldn’t work here) and then generates a unique file name based on the MD5 hash of the generated script:

     {{ $code_fragments := slice }}
     {{ range (.page.Scratch.Get .set) }}
         {{ $code_fragments = $code_fragments | append .Content }}
     {{ end }}
    
     {{ $code_fragments = delimit $code_fragments "" }}
     {{ $resource_path := printf .outPath (md5 $code_fragments) }}
     {{ $resource := $code_fragments | resources.FromString $resource_path }}
     {{ return $resource }}
    

With this at hand, my partial layouts can now use e.g.

{{ partial "resource/register_script" (dict "scratch" .scratch "resource" (resources.Get "js/collapsible-tree.js")) }}

to register a resource for inclusion (here: js/collapsible-tree.js, for pages which happen to use a tree control)

The baseof.html layout then uses

{{ .Scratch.Set "scripts" slice -}}

at the very top (to setup the ‘scripts’ slice which register_script depends on) plus

{{ $resource := partial "resource/combine" (dict "page" . "set" "scripts" "outPath" "js/script-%s.js") }}
{{ $script := $resource | minify | fingerprint }}
<script type="text/javascript" src="{{ $script.RelPermalink }}" integrity="{{ $script.Data.Integrity }}"></script>

at thee bottom of <body> to get the combined script, minimize it, fingerprint it.

1 Like