Ces points s’adressent principalement aux personnes qui développent leur propre thème, ou qui adaptent un thème existant.
Gestion du thème
Installation
Comme il est indiqué dans la documentation du Hugo, l’installation d’un thème ne peut pas se faire avec la commande git clone
habituelle. Netlify ne pourra déployer le site. La méthode préconisée consiste à utiliser les sous-modules (commande git submodule
). Je vous renvoie à l’article Révisions GIT: épisode 6.
Exemple avec le thème Universal
$ cd themes
$ git submodule add https://github.com/devcows/hugo-universal-theme
Modifications du thème
Que vous soyez l’auteur ou non du thème, vous serez amené à le mettre à jour régulièrement, en parallèle des mises à jour du site lui-même. Dans ce cas, il faut garder à l’esprit que nous n’avons pas un dépôt GIT mais deux : un pour le site, et un pour le thème :
- Si nous sommes dans l’un des répertoires du thème, nous sommes dans le dépôt du thème (dépôt principal),
- Si nous sommes dans l’un des répertoires du site, nous sommes dans le dépôt du site (dépôt secondaire).
Les modifications du thème d’une part, et celle du contenu, d’autres part, sont donc dissociées.
Comme nous en l’avons déjà décrit dans l’article Révisions GIT: épisode 6, le cycle des modifications d’un thème doit suivre les étapes suivantes :
- Au niveau du thème : Effectuer les modifications, ainsi que les opérations sur le dépôt git local (
git fetch
,git add/commit
, …), - Effectuer un
git push
des modifications du thème vers le dépôt distant, - Intégrer les modifications du thème, au dépôt du site (dépôt principal), avec les commandes
git add
, etgit commit
, - Effectuer un
git push
du dépôt principal.
L’oubli du point 2 conduira à un échec du côté de Netlify, comme le montre la figure 1.
Publication
Avec la plateforme Netlify, la génération et la publication des pages du site peuvent être complètement automatisées (Figure 2).
- Netlify s’intégre à la plateforme GitHub,
- Un
pull request
sur une branche GitHub déclenche la génération du site, et sa publication en mode « prévisualisation », - Une fusion de cette branche vers la branche
main
oumaster
, déclenchera la génération du site, et sa publication finale.
En pratique :
#Nous sommes dans le répertoire du thème
$ pwd
/.../.../EGE-Blog/themes/Minimal-Blank
# Edition de la feuille de styles
$ edit styles.css
$ git commit -a -m "Add styles for footnotes" # Commit du changemen au niveau du thème
$ git push oririn main # On pousse les modifs au niveau du dépôt distant
# On change de répertoire pour se placer au niveau du site
$ cd ../..
# Status du dépôt local du site
$ git status
On branch git_hugo # Nous sommes dans la branche git_hugo
Your branch is up to date with 'origin/git_hugo'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: themes/Minimal-Blank (new commits)
# Validation des modifications du thème.
$ git commit -a -m "Theme update"
[git_hugo 21f44f5] Update of the theme
1 file changed, 1 insertion(+), 1 deletion(-)
# Pousser les modifications de la branche git_hugo vers le dépôt distant
$ git push origin git_hugo
GitHub qui vient de recevoir une mise à jour d’une branche, va proposer de créer une pull request (figure 3).
La création de cette pull request va déclencher la génération du site, côté Netlify (figures 4 et 5)
Une fois que la génération du site est complète, et le site disponible en mode preview (génération sans erreur) dans Netlify, Github affiche les résultats des vérifications effectuées (figure 6).
Il ne reste plus qu’à confirmer la fusion en appuyant sur Merge pull request. La fusion de la branche en cours vers la branche main/master
va déclencher la génération et la publication finale du site (figure 7)
Manipulation de fichiers
Au niveau du thème, nous avons parfois besoin de manipuler des fichiers, comme pour gérer les images, par exemple. Dans ce cas, il y a plusieurs risques potentiels :
- Des erreurs au niveau des chemins, qui sont différents entre l’arborescence de développement, et l’arborescence générée,
- Des problèmes de casse. Ces problèmes se posent particulièrement si vous développez sous Windows. Ce système ne fait pas de différence entre minuscule et majuscule, contrairement aux systèmes Linux de l’hébergeur. Donc, nous pouvons avoir un site qui fonctionne parfaitement sur notre machine, et ne plus fonctionner du tout en mode preview, ou production,
- Des chemins « codés en dur » (hardcoded), qui doivent être ensuite modifiés en fonction des environnements.
Les conseils pour réduire ces risques sont
- Utiliser, autant que possible, les fonctions de Hugo pour accéder aux données,
- Utiliser la même casse pour toute l’arborescence (minuscule par exemple),
- Respecter les conventions de Hugo pour la gestion des données (utilisation des répertoires
/data
,/assets
, ou/static
).
Images
Un exemple d’opérations sur les images. Ici, à partir d’un chemin relatif, nous utilisons la fonction GetMatch
pour obtenir le chemin complet de l’image. A partir de là, nous avons un accès aisé aux caractéristiques de l’image, et aux fonctions de manipulations.
{{- $size := 320 -}}
{{- $imgpath := <relative path to the image> -}}
{{- $image = .Resources.GetMatch $imgpath -}}
{{- with $image -}}
{{- $width := int .Width -}}
{{- $img_resized := $image.Resize (printf "%dx" $size) -}}
{{- end -}}
Manipulation des données
Dans le thème Goyat, j’utilise un fichier pour décrire la configuration du pied de page. Ma structure de fichier est la suivante :
- J’ai un fichier
/data/footer.json
qui contient la configuration voulue par l’utilisateur du thème, - Le fichier
/themes/goyat/data/default_params.json
contient les valeurs par défaut (valeurs prises si elles ne figurent pas dans le fichier/data/footer.json
.
├── config.toml
├── archetypes
├── content
├── data
| └── footer.json
├── layouts
├── static
└── themes
└── <nom du thème>
├── assets
├── data
| └── default_params.json
├── i18n
├── layouts
└── theme.toml
Le code suivant
- parcourt le fichier
/data/footer.json
, - récupère des paramètres dans ce fichier, comme par exemple
.limitedwidth
, ou.columns
, - et va chercher les valeurs par défaut si nécessaire, comme
site.Data.default_params.widgets.areas.limitedwidth
par exemple.
{{- range sort site.Data.footer.Rows "weight" -}}
<div class="footer-{{- .name }}">
{{- $limit := cond (.limitedWidth | default site.Data.default_params.widgets.areas.limitedwidth) "limit-width" "" -}}
<div class="container {{ $limit -}}">
{{- $columns := .columns | default site.Data.default_params.widgets.areas.columns -}}
... ...
</div>
</div>
{{- end -}}
Autre exemple, avec la lecture d’un fichier JSON.
{{- $filepath := path.Join "data" .params.filename -}}
{{- if os.FileExists $filepath -}}
{{- $data := getJSON $filepath -}}
{{- with $data -}}
{{- range sort $data.posts "visit" "desc" -}}
... ...
{{- end -}}
{{- end -}}
{{- end -}}
La page de contact
Pour la page de contact, j’utilise pour l’instant les mécanismes offerts par Netlify : ce n’est pas hyper-ergonomique, mais c’est facile à mettre en place. La page fonctionne très bien. Cependant, si les SPAMS sont bien identifiés (grâce à Akismet), nous les retrouvons tous dans la rubrique SPAM du formulaire, et l’interface Netlify ne propose pas de bouton pour les effacer tous en même temps. Il faut donc y aller régulièrement, et les effacer un par un, ce qui est plutôt fastidieux.
Je conseille donc de mettre en place, assez rapidement, l’une des deux méthodes de filtrage proposées par Netlify : Soit le pot de miel (honey pot), soit le Captcha.
- Le pot de miel consiste à mettre en place un champ caché dans le formulaire : si le champ est saisi, alors il ne s’agit pas d’un humain,
- Le challenge Captcha proposé par la plateforme est le reCaptcha 2.
J’ai mis en place, dans un premier temp, le pot de miel : le bilan est positif, mais il laisse encore passer pas mal de SPAMS (un peu plus de 1 par heure). Après quelques jours. Je suis donc passé à Captcha 2, dans sa version simplifiée. Les résultats sont beaucoup plus efficaces.
Voici le formulaire de contact de ce blog :
<form id="contact-form" name="contact" method="POST" data-netlify-recaptcha="true" data-netlify="true">
<div class="form-group">
<label for="form-your-name">{{- i18n "your-name" -}}</label>
<input type="text" class="form-control" id="form-your-name" name="form-your-name">
</div>
<div class="form-group">
<label for="form-your-email">{{- i18n "email-address" -}}</label>
<input type="email" class="form-control" id="form-your-email" name="form-your-email">
</div>
<div class="form-group">
<label for="form-subject">{{- i18n "subject" -}}</label>
<input type="text" class="form-control" id="form-subject" name="form-subject">
</div>
<div class="form-group">
<label for="form-msg">{{- i18n "your-message" -}}</label>
<textarea class="form-control" id="form-msg" name="form-msg" rows="5"></textarea>
</div>
<div data-netlify-recaptcha="true"></div>
<button type="submit" class="btn btn-primary contact-button" value="submit">{{- i18n "submit" -}}</button>
</form>
L’activation de Captcha2 se fait simplement, en ajoutant l’attribut data-netlify-recaptcha="true"
au formulaire.
Gestion des déploiements
Dans un paragraphe précédent, nous avons vu que Netlify propose deux environnements: preview et Production. Au final, avec notre poste de travail, nous avons 3 environnements
- L’environnement de développement,
- L’environnement de
preview
, celui dont la construction se déclenche avec lespull-request
- L’environnement de
production
.
En fonction de ces trois environnements, des éléments peuvent différer :
- Les articles à afficher sont différents. Nous pouvons avoir des options comme
--buildFuture
pour les environnements dedev
etpreview
- Les urls sont différentes :
localhost
pour le développement, une url avec l’identifiant de déploiement pour lepreview
, et le nom du domaine du site pour laproduction
Si l’on se contente du fichier de configuration du site (config.toml
), avec des paramètres comme baseURL
, nous aurons des résultats dans certains environnements, et quelques limitations dans d’autres.
Une autre solution consisterait à utiliser les paramètres de déploiement dans l’interface de Netlify.Mais cette option a ses limites : comment faire varier les paramètres en fonction de l’environnement ?
La solution la plus simple et la plus souple consiste à
- Enlever les valeurs du fichier
config.toml
qui peuvent varier en fonction de l’environnement (par exemplebaseURL=""
), - Passer ces valeurs à NetLify via un autre fichier de configuration
netlify.toml
, que l’on place à la racine du site.
A titre d’exemple, voici le fichier de configuration de mon blog :
[context.production]
command = "hugo --minify --baseURL=$URL"
[context.production.environment]
HUGO_VERSION = "0.101.0"
HUGO_ENV = "production"
[context.deploy-preview]
command = "hugo --buildFuture --baseURL=$DEPLOY_URL --minify"
[context.deploy-preview.environment]
HUGO_VERSION = "0.101.0"
HUGO_ENV = "preview"
Au passage, l’autre avantage d’utiliser cette méthode, est qu’elle offre suffisamment de souplesse pour réaliser des tests de versions, ou de paramètres en mode preview, avant d’effectuer ces changements en mode production.
Conclusion
Netlify propose une solution très efficace pour le déploiement automatique d’un site Hugo.
Si vous êtes débutant avec Hugo, et vous avez l’intention d’utiliser Netlify comme solution d’hébergement, je vous conseille de démarrer les déploiements asez tôt dans votre processus de développement. Cela vous permettra de repérer rapidement d’éventuelles différences de comportement entre votre environnement de développement, et l’environnement Netlify, et donc d’ajuster votre code rapidement.
Les documentations Hugo et Netlify sont claires et assez exhaustives pour répondre à la plupart des problèmes rencontrés.
Références
- Build environment variables sur le site Netlify
- Hugo on Netlify sur le site Netlify
- Host on Netlify sur le site GoHugo
Commentaires