Introduction

Hugo est un générateur de site statique très performant. Je l’ai récemment utilisé et j’ai été impressionné par la vitesse de génération, tout en prenant en charge la gestion des CSS et JavaScript. La prise en main peut être un peu plus difficile que Jekyll mais cela en vaut vraiment le coût.

L’installation est très simple, quel que soit l’OS. La procédure est décrite dans la doc.

La version "étendue (extended)" est nécessaire pour traiter les fichiers SASS/SCSS.

Vous aurez également besoin de npm.

C’est parti !

Une fois les prérequis installés, procédons à la création du site :

hugo new site mysite
cd mysite

Installation des dépendances

Les dépendances seront installées à l’aide de npm. Initialisons npm avec la commande suivante. Les paramètres demandées importent peu.

npm init

Puis installons les dépendances :

npm install bootstrap jquery popper.js --save
npm install postcss postcss-cli autoprefixer --save

Gestion des feuilles de style

Un de mes objectifs est de pouvoir personnaliser Bootstrap (couleurs, etc.) ou d’utiliser les variables.

Pour ce faire, créer le répertoire assets/sass avec la commande :

mkdir assets/scss
Ajouter l’argument -p à la commande mkdir sous Linux.

Sous assets/scss, créez les fichiers :

  • variables.scss : Contiendra les surcharges et des variables globales

  • style.scss : Contiendra le point de départ des personnalisations pour les différentes pages, composants, etc.

  • main.scss : Se chargera des imports et surcharges Bootstrap. C’est l’unique fichier qui sera utilisé comme feuille de style.

Ainsi, main.scss contiendra quelque chose comme ci-dessous ou une version plus optimisée des imports Bootstrap :

@import "variables";
@import "../../node_modules/bootstrap/scss/bootstrap";
@import "styles"

Gestion des dépendances JavaScript

Hugo attend les assets dans le répertoire assets, afin de pouvoir appliquer des traitements. Je vais donc utiliser les directives mount d’Hugo.

Ainsi, dans le fichier config.toml, ajoutez les lignes suivantes :

[module]
    [[module.mounts]]
        source = 'content'
        target = 'content'
    [[module.mounts]]
        source = 'static'
        target = 'static'
    [[module.mounts]]
        source = 'layouts'
        target = 'layouts'
    [[module.mounts]]
        source = 'data'
        target = 'data'
    [[module.mounts]]
        source = 'assets'
        target = 'assets'
    [[module.mounts]]
        source = 'i18n'
        target = 'i18n'
    [[module.mounts]]
        source = 'archetypes'
        target = 'archetypes'
    [[module.mounts]]
        source = "node_modules/jquery/dist/jquery.min.js"
        target = "assets/js/vendor/jquery.min.js"
    [[module.mounts]]
        source = "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
        target = "assets/js/vendor/bootstrap.min.js"
    [[module.mounts]]
        source = "node_modules/popper.js/dist/popper.min.js"
        target = "assets/js/vendor/popper.min.js"

Comme c’est décrit dans la doc, que je traduis rapidement ici :

Lorsque vous ajoutez un montage, le montage par défaut de la racine cible concernée est ignoré : assurez-vous de l'ajouter explicitement.

Gabarit

Il s’agit du "gros" du travail. Le gabarit Hugo doit prendre en compte le CSS personnalisé et les dépendances JavaScript.

Il est possible de découper un gabarit en plusieurs fichiers. C’est à l’appréciation de chacun. Personnellement, je préfère garder les choses assez séparées et reposer sur le mécanisme de cache interne pour les choses qui ne varient pas en fonction des pages.

La structure du répertoire layouts peut ainsi ressembler à :

  • _default

    • baseof.html

  • partials

    • footer

      • scripts.html

      • site-footer.html

    • head

      • favicons.html

      • head.html

      • styles.html

    • header

      • site-header.html

  • index.html

Si l’on se focalise sur la partie CSS et JavaScript, on a alors 

scripts.html
<!-- Vendor JS Files -->
{{ $jquery := resources.Get "js/vendor/jquery.min.js" }}
{{ $popperjs := resources.Get "js/vendor/popper.min.js" }}
{{ $bootstrap := resources.Get "js/vendor/bootstrap.min.js" }}
{{ $js := slice $jquery $popperjs $bootstrap | resources.Concat "js/bundle.js" | minify | fingerprint }}

<script src="{{$js.RelPermalink}}" integrity="{{ $js.Data.Integrity }}" crossorigin="anonymous"></script>

<!-- Template Main JS File -->
{{ $mainJs := resources.Get "js/main.js" | js.Build "main.js" | minify | fingerprint }}
<script type="text/javascript" src="{{ $mainJs.RelPermalink }}" integrity="{{ $mainJs.Data.Integrity }}" crossorigin="anonymous"></script>
styles.html
{{ $options := (dict "targetPath" "css/style.css" "outputStyle" "compressed" "enableSourceMap" true) }}
{{ $style := resources.Get "scss/main.scss" | toCSS $options | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $style.RelPermalink }}" integrity="{{ $style.Data.Integrity }}">

Les autres fichiers sont relativement inintéressant. Je les mets ici pour avoir un exemple complet.

baseof.html
<!DOCTYPE html>
<html lang="fr">
{{ partial "head/head.html" . }}
<body>
    {{ partialCached "header/site-header.html" . }}
    {{ block "main" . }}
    <!-- The part of the page that begins to differ between templates -->
    {{ end }}
    </main><!-- End #main -->
    {{ partial "footer/site-footer.html" . }}
    {{ partialCached "footer/scripts.html" . }}
</body>
</html>
head.html
<head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article# website: http://ogp.me/ns/website#">
    <meta charset="utf-8">
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <title>
        {{ if not .IsHome }}
        {{ .Title | default .Site.Title }} | {{ .Site.Params.Description }}
        {{ else }}
        {{ .Title  }} | {{ .Site.Title }}
        {{ end }}
    </title>
    <meta name="description" content="{{.Description | default .Site.Params.Description}}"/>
    <meta name="robots" content="index, follow"/>
    <link rel="canonical" href="{{ .Permalink}}" />  
    {{ template "_internal/opengraph.html" . }}
    {{ template "_internal/twitter_cards.html" . }}
    {{ partialCached "head/styles.html" . }}
    {{ partialCached "head/favicons.html" . }}
</head>
index.html
{{ define "main" }}
Hello World
<a class="btn btn-primary">Un bouton</a>
{{ end }}

Git

Créez un fichier .gitignore contenant

public
resources
node_modules

Puis, effectuez les habituels commandes :

git init
git add -A
git commit -m "🎉first commit🎉"
git branch -m master main

Et voilà

hugo ou hugo serve vont vous permettre d’admirer ce premier canvas Hugo+Bootstrap.