Un site web simple avec le plus simple des générateurs de site statique
Source : Making a Simple Web Site with the Simplest Static Site Generator, Level 1 de Zach Leatherman
Il existe des centaines de générateurs de site statique et il en
arrive toujours de nouveaux. Après avoir longtemps utilisé Jekyll,
Zach Leat, développeur front-end chez
Filament Group, a décidé de s’inspirer des
principes de Jekyll pour les porter et les étendre grâce à l’écosystème de npm
qu’il manipule au quotidien.
Ce nouveau générateur vise donc les développeurs front end et leur donne le
choix du langage de templating (Liquid par
défaut comme dans Jekyll et aussi
tout plein d’autres qu’on peut mélanger à loisir
bien connus des développeurs JS) tout en leur offrant la puissance de npm
.
Zach nous propose un premier aperçu de son fonctionnement.
Voici Eleventy, le générateur de site statique le plus simple et le plus intuitif. Avec Eleventy, vous pouvez générer des sites à partir de données de manière simple et rapide — et vous concentrer sur un contenu facile à maintenir, conçu pour durer longtemps. Faites en sorte que votre site dure 10 ans, pas 10 mois.
Installation
Si ce n’est pas déjà fait, installez node.js et npm (ils sont dispos sous la forme d’un seul et unique paquet). Eleventy ne fonctionne qu’à partir de
node --version
8.0.0 ou plus.Ensuite, installez l’utilitaire en ligne de commande, disponible sur npm :
npm install -g @11ty/eleventy
En avant
Faisons un site web pour notre collection d’images GIF. Une interface pour notre propre domaine bukk.it. Appelons ça Giffleball.
Création des fichiers
Créons un dossier pour notre tout nouveau site web.
mkdir giffleball
Ajoutons quelques images à notre site. Voici une sélection d’images d’oiseaux tirée de l’honorable site bukk.it.
Sauvegardez ces images dans un dossier img
à l’intérieur de notre répertoire
giffleball
.
giffleball/
img/???.jpg (nouveau)
img/….jpg (nouveau)
img/parrot.gif (nouveau)
Création d’un gabarit de page
Faisons un gabarit de page ! Créez un fichier nommé index.html
dans le
répertoire giffleball
.
giffleball/
index.html (nouveau)
img/???.jpg
img/….jpg
img/parrot.gif
Créons une liste avec des liens vers nos images GIF dans le fichier index.html
:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Giffleball</title>
</head>
<body>
<h1>Giffleball</h1>
<ul>
<li><a href="img/???.jpg">???.jpg</a></li>
<li><a href="img/….jpg">….jpg</a></li>
<li><a href="img/parrot.gif">parrot.gif</a></li>
</ul>
</body>
</html>
Jusqu’ici, rien d’extraordinaire. Mais nous pouvons déjà lancer eleventy
et
générer notre site. Nous passerons en option les extensions de fichier que nous
voulons voir eleventy
traiter :
~ cd giffleball
~/giffleball $ eleventy --formats=html,gif,jpg
Writing _site/index.html from ./index.html.
Wrote 1 file in 0.07 seconds
Cela a pour effet de créer un nouveau site web dans le répertoire _site
. Si
vous souhaitez que le site soit généré dans un autre dossier, précisez le nom du
répertoire en argument avec l’option --output
:
~/giffleball $ eleventy --output=ailleurs
Writing ailleurs/index.html from ./index.html.
Wrote 1 file in 0.07 seconds
Basons-nous sur des données
OK, jusqu’ici nous aurions simplement pu charger notre fichier index.html
dans
le navigateur et le résultat aurait été le même. Il n’y a aucune différence en
entrée et en sortie. Ajoutons donc une petite touche eleventy
. Déplaçons
certaines données de la page dans notre
front matter :
---
siteTitle: Giffleball
images:
- ???.jpg
- ….jpg
- parrot.gif
---
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ siteTitle }}</title>
</head>
<body>
<h1>{{ siteTitle }}</h1>
<ul>
{% for filename in images %}
<li><a href="img/{{ filename }}">{{ filename }}</a></li>
{% endfor %}
</ul>
</body>
</html>
Nous avons ajouté le titre du site (utilisé à deux endroits) ainsi que la liste des images dans notre front matter.
Par défaut dans Eleventy, le moteur du rendu liquid
est disponible pour les
fichiers HTML et les fichiers Markdown. Eleventy supporte une large gamme de
moteurs de rendu (jetez un œil sur
la liste complète) qui sont
disponibles lorsque vous utilisez une extension de fichier spécifique. Par
exemple notre fichier index.html
aurait pu s’appeler index.liquid
et le
fonctionnement aurait été le même :
~/giffleball $ mv index.html index.liquid
~/giffleball $ eleventy --formats=liquid,html,jpg,gif
Writing _site/index.html from ./index.liquid.
Wrote 1 file in 0.07 seconds
Bien sûr vous pouvez modifier les paramètres par défaut, nous verrons ça plus tard (ou vous pouvez dès à présent jeter un œil au fichier README).
L’utilisation d’un moteur de rendu présente plusieurs avantages :
Modifier vos données au même endroit. Pour changer le titre du site, nous n’avons besoin de le modifier qu’à un seul endroit (le front matter) au lieu de deux. Pour ajouter ou supprimer des images nous n’avons pas à toucher au modèle de code HTML.
Modifier le balisage des liens vers nos images en une fois. Admettons que nous souhaitions modifier le code HTML de notre liste d’images. Comme nous nous basons sur des données, nous pouvons modifier le modèle de code HTML dans notre boucle plutôt que de devoir modifier chaque
<li>
individuellement. Trois passent encore mais vous imaginez si notre site listait 300 images ?Les caractères spéciaux contenus dans les noms de fichier. Quand je regarde dans mon navigateur, on dirait que mon serveur web n’aime pas trop des noms tels que
???.jpg
. Le fichier ne s’affiche pas correctement. Que se passerait-il si nos noms de fichiers comportaient des caractères bizarres que notre serveur web ou notre navigateur ne sait pas traiter ? Nous devons les échapper ! La syntaxe du moteur de template Liquid a juste ce qu’il nous faut : un filtreurl_encode
. Mettons notre gabarit à jour pour en bénéficier :
{% for filename in images %}
<li><a href="img/{{ filename | url_encode }}">{{ filename }}</a></li>
{% endfor %}
Ah c’est bien mieux. Ça marche nickel.
J’espère que vous vous rendez compte de l’avantage d’utiliser des moteurs de rendu et un générateur de site statique pour vos sites web.
Ajoutons un filtre
Faisons un truc plus compliqué. Affichons la taille de chacune des images GIF à
côté de leur lien. Nous pouvons faire ça à l’aide d’un filtre. Les filtres
s’ajoutent dans le fichier de configuration — un fichier .eleventy.js
— créons
en un. Il devrait ressembler à ça :
module.exports = function(eleventyConfig) {};
Si vous ne le nommez pas .eleventy.js
, chaque fois que vous allez lancer la
commande eleventy
il faudra lui passer le nom du fichier de configuration en
option à l’aide de --config=maConfig.js
. C’est bien plus simple de s’en tenir
au nom par défaut.
Ajoutons notre filtre à l’aide de la méthode .addFilter
. Appelons-le
filesize
et commençons par lui faire retourner un texte tout bête :
module.exports = function(eleventyConfig) {
eleventyConfig.addFilter("filesize", function(path) {
return "0 KB";
});
};
Bien entendu, notre filtre n’est pas bon, car nous nous contentons de retourner
"0 KB"
à chaque fois. Mais vérifions d’abord qu’il marche.
Ouvrons notre modèle index.html
et regardons à quoi ressemble notre boucle
pour le moment :
<ul>
{% for filename in images %}
<li><a href="img/{{ filename | url_encode }}">{{ filename }}</a></li>
{% endfor %}
</ul>
Vous avez fait attention à la façon dont nous avons utilisé le filtre natif
url_encode
fourni par le moteur de rendu Liquid ? Maintenant que nous avons
créé le nôtre, ajoutons un appel à notre petit filtre maison, comme ceci :
<ul>
{% for filename in images %}
{% capture path %}img/{{ filename }}{% endcapture %}
<li><a href="img/{{ filename | url_encode }}">{{ filename }}</a> {{ path | filesize }}</li>
{% endfor %}
</ul>
Bien entendu, la magie a lieu dans {{ path | filesize }}
. Mais notez comment
nous utilisons la balise {% capture %}
de Liquid pour créer une nouvelle
variable path
avec Liquid, que nous passons ensuite à notre filtre.
Maintenant, lançons eleventy
pour générer les fichiers.
~/giffleball $ eleventy --formats=html,gif,jpg
Writing _site/index.html from ./index.html.
Wrote 1 file in 0.07 seconds
Cela va générer le code suivant dans le fichier _site/index.html
(ici nous ne
montrons que le rendu de la liste et pas le fichier HTML entier pour faire
court):
<ul>
<li><a href="img/%3F%3F%3F.jpg">???.jpg</a> 0 KB</li>
<li><a href="img/%E2%80%A6.jpg">….jpg</a> 0 KB</li>
<li><a href="img/parrot.gif">parrot.gif</a> 0 KB</li>
</ul>
OK, c’est presque ça — mais c’est quoi tous ces espacements ? (Notez que c’est
une question purement rhétorique à laquelle je vais m’empresser de répondre tout
de suite.) Lors du traitement des modèles, Liquid ne supprime pas les retours à
la ligne et les espaces autours des balises Liquid. Heureusement pour nous,
Liquid fournit un outil pour contrôler ces espacements. Il faut utiliser {%-
à
la place de {%
pour supprimer l’espacement avant la balise Liquid. Et
indépendamment on peut aussi utiliser -%}
à la place de %}
à la fin pour
supprimer l’espace après la balise Liquid. L’un ou l’autre. Les deux.
Personnellement je trouve que ça rend mieux avec juste {%-
au début. Il est
important pour moi d’avoir une vue du code source qui soit propre, alors
nettoyons tout ça :
<ul>
{%- for filename in images %}
{%- capture path %}img/{{ filename }}{% endcapture %}
<li><a href="img/{{ filename | url_encode }}">{{ filename }}</a> {{ path | filesize }}</li>
{%- endfor %}
</ul>
Ce qui produit :
<ul>
<li><a href="img/%3F%3F%3F.jpg">???.jpg</a> 0 KB</li>
<li><a href="img/%E2%80%A6.jpg">….jpg</a> 0 KB</li>
<li><a href="img/parrot.gif">parrot.gif</a> 0 KB</li>
</ul>
Magnifique.
C’est encore un peu tôt pour nous réjouir, notre filtre n’est pas fini
OK, faisons en sorte que notre filtre serve à quelque chose plutôt que de
simplement retourner systématiquement "0 KB"
. Modifiez votre fichier
.eleventy.js
comme ceci :
const fs = require("fs");
module.exports = function(eleventyConfig) {
eleventyConfig.addFilter("filesize", function(path) {
let stat = fs.statSync(path);
if (stat) {
return (stat.size / 1024).toFixed(2) + " KB";
}
return;
("");
});
};
C’est la manière la plus simple de le faire marcher, ça n’ajoute aucune nouvelle
dépendance lors d’un npm install
.
Allons plus loin à l’aide de NPM
Un des gros avantages d’Eleventy sur d’autres générateurs de site statique comme
Jekyll ou Hugo, c’est l’accès à tout l’écosystème de NPM. Il y a tellement
d’excellents modules. Si vous êtes assez courageux pour jouer avec npm
, lancez
cette commande pour générer un fichier package.json
pour notre projet :
~/giffleball $ npm init -f
Nous pouvons maintenant installer des modules cools à notre projet, comme file-size pour des tailles de fichiers plus lisibles.
~/giffleball $ npm install --save file-size
+ file-size@1.0.0
added 1 package in 1.491s
Utlisons-le pour coder notre filtrer dans le fichier .eleventy.js
:
const fs = require("fs");
const filesize = require("file-size");
module.exports = function(eleventyConfig) {
eleventyConfig.addFilter("filesize", function(path) {
let stat = fs.statSync(path);
if (stat) {
return filesize(stat.size).human();
}
return "";
});
};
Ce qui nous donne :
<ul>
<li><a href="img/%3F%3F%3F.jpg">???.jpg</a> 44.52 KiB</li>
<li><a href="img/%E2%80%A6.jpg">….jpg</a> 55.39 KiB</li>
<li><a href="img/parrot.gif">parrot.gif</a> 2.05 KiB</li>
</ul>
Félicitations ! Vous avez ajouté un filtre et tiré profit du vaste et immense écosystème NPM.
J’espère que vous appréciez la puissance offerte par l’utilisation de filtres dans nos fichiers de gabarits. Ils peuvent transformer des contenus simples à l’aide de la puissance de l’écosystème NPM.
À suivre
Dans la prochaine partie nous verrons comment faire marcher ensemble plusieurs fichiers de gabarits avec des fichiers de mise en page et des fichiers de données externes.