How to Minify Javascript When Using Hugo Variables.
How to use hugo variables inside javascript when minification is required.implementing Hugo Codex’ consent.html
When implementing the Hugo Codex cookie consent method. I wanted to have all the cookie functions and logic minified. Hugo uses the tdewolff/minify. The minify methods are configurable as defined in the documentation.
What I did notice is that using hugo’s templating system did not allow me to minify the output.
Example snippet from consent.html :
<script>
const scripts = [];{{ range $index, $item := (where hugo.Data.consent.items "is_functional" false) }}
scripts[{{ $index }}] = "/js/{{ $item.script_file }}";{{ end }}
function createCookie(name,value,days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
function loadConsentScripts(consentValue) {
scripts.forEach(function(value,key){
//console.log('script'+key+' is set to ' +consentValue[key]+' and is file '+value);
if(consentValue[key]=="1") {
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = value;
document.body.appendChild(s);
}
});
}
</script>
The above code when moved to its own file, wouldn’t populate the array variable scripts with a corresponding enumerated index and the script path when minified.
The challenge is that the script paths are loaded from a yaml file which is populated with the hugo variable call of $item := (where hugo.Data.consent.items “is_functional” false))
execute of template failed at <$cookieFunctions.RelPermalink>: error calling RelPermalink: MINIFY: failed to transform "/cookieFunctions.js" (text/javascript): unexpected $index in expression on line 5 and column 14
5: ยทยทยทยท{{ range $index, $item := (where .Site.Data.consent.i...
Overview of steps/actions taken
- Copy all relevant script logic to a unique file (cookieFunctions.js) and remove all javascript functionality from consent.html.
- Remove all content in consent.html that is javascript related.
- Move all relevant script logic to a file named cookieFunctions.js
- use IIFEs.
Using Immediately Invoked Function Expressions allows minify to anonymize the function names. Other best practices for using IIFEs exist and are beyond the scope of this write up and my area of expertise.
- use IIFEs.
IIFE example encapsulation
(function() {
function ... {}
})();
The solution for including hugo variables in a javascript minified file was not immediately evident to me and took some research. My first path was trying to escape/ignore the hugo variable brakcets ‘{{ and }}’ with a hugo configuration option. example: templateDelims = [’{{’, ‘}}’]. The change to template delims did not yield proper results.
Then I was able to find the ExecuteAsTemplate function. Chaining the commands together yielded the proper result. Here is the code snippet that allowed hugo variables to populate a minified javascript file.
{{- $cookieFunctions := resources.Get "cookieFunctions.js" |resources.ExecuteAsTemplate "cookieFunctions.js" . | minify -}}
<script src="{{- $cookieFunctions.RelPermalink -}}"></script>
The above code modifications now allow for the minification of all the cookie functions while allowing the consent.yaml to control what scripts are loaded based upon the users selection.
Many thanks to @jhvanderschee and [email protected]. for the excellent template versions of consent.html and consent.yaml. The HugoCodex Site is worth your time if you are working with Hugo
If you would like email or rss feed updates. Visit the Subscribe page