Publié le

Mon blogue personnel est un sérieux signe du temps qui file à toute allure. Le temps d’un clin d’œil, me semble-t-il, et voilà que je me rends compte que je n’y ai publié aucun article depuis cinq ans. Tout aussi gênant : Jusqu’à ce que soit complétée, en août dernier, la refonte dont je vous entretiendrai ici, le design du site était tel que je l’avais dessiné en… 2005, soit à l’époque où Internet Explorer 6 régnait sur le Web en maître quasi absolu, où les rares écrans tactiles fonctionnaient uniquement à l’aide d’un crayon, et où Facebook n’était connu que sur quelques campus universitaires…

Avant et après

J’ai tout de même écrit quelques articles au cours de ces cinq années, des textes destinés au site de mon entreprise, Whisky Echo Bravo. Ce n’est donc pas un hasard si le dernier article de mon site personnel coïncidait avec le lancement du site web de Whisky Echo Bravo ! En fin de compte, je ne maintenais mon site personnel en place que parce qu’il recevait, malgré sa désuétude, un bon nombre de visiteurs.

La motivation me manquait pour faire une sérieuse mise à jour. Mes projets personnels sont un territoire d’expérimentation pour de nouveaux outils et de nouvelles techniques, mais une refonte de mon site ultra simple avec Drupal n’aurait pu m’apporter tellement de nouveauté compte tenu de ma forte expérience avec Drupal. C’est donc à travers Python, ce langage de programmation qui prend de plus en plus de place dans mon arsenal d’outils, que m’est finalement venue la motivation. Refaire ce site n’allait pas exiger des exploits de programmation, mais fournissait néanmoins une occasion d’explorer une petite partie de l’écosystème Python.

Choisir un générateur de site statique

La fonctionnalité d’un système de gestion de contenu (CMS) dynamique (tel que Drupal) est en constante adaptation, par exemple en fonction des droits de l’utilisateur, des configurations, des contenus créés ou modifiés. Bénéficier d’un tel degré de dynamisme a un coût, en complexité logicielle, en performance, en risques de sécurité et en maintenance. Pourtant, je suis le seul producteur de contenu sur mon site et le temps a prouvé que j’y produis très peu… Avec un contexte aussi statique, à quoi bon disposer de toutes ces fonctions dynamiques? Pendant cette accalmie de cinq années lors desquelles je n’ai publié aucun article et ne me suis presque jamais connecté au système, plusieurs dizaines d’alertes de sécurité et de mises à jour du noyau Drupal ont été publiées, de même que des nouvelles versions majeures de PHP, autant de soucis quant à la continuité du système, alors même que je n’avais ni le temps ni la motivation de m’en préoccuper.

C’est donc tout naturellement que je me suis tourné vers un générateur de site statique pour cette refonte. Avec un générateur de site statique, l’environnement de production des contenus est complètement détaché de celui de la consommation des contenus. Lorsque de nouveaux contenus sont produits, on génère une nouvelle « image » du site, puis on la déploie sur le serveur web. Cette image n’est constituée que de bêtes fichiers HTML statiques, un fichier pour chaque URL offert par le site. La performance est maximale, puisqu’aucun code dynamique et aucune requête de base de données ne sont exécutés. Les fichiers sont statiques et identiques pour tous les visiteurs. Ceci ne convient certes pas à tous les types de sites, mais pour mon site extrêmement statique? Idéal !

Si ce type de déploiement nous ramène aux origines du Web, l’environnement de production, lui, est contemporain. Les fichiers HTML ne sont pas édités manuellement, mais générés à l’aide de dispositifs qui s’apparentent à ceux d’un CMS dynamique. Ceux-ci interprètent et transforment les contenus (textes et médias), puis construisent la navigation, les pages HTML, les fils RSS, etc.

Même si une mise à jour logicielle venait à compromettre le fonctionnement de l’outil, la façade publique du site, statique et autonome, ne serait pas compromise. Le seul stress découlant d’un tel problème serait l’urgence — rarissime chez moi — d’un nouveau contenu à publier !

Découvrir Pelican

Dans mes recherches d’un outil de génération statique construit en Python, Pelican a rapidement émergé.

Pelican épluche une collection de fichiers textes, où chaque fichier représente un contenu, par exemple en format reStructuredText, Markdown ou HTML, en extrait les données et métadonnées, puis génère une sortie HTML articulée par des gabarits. Les listes de contenus, telles les archives, les contenus associés à chaque catégorie et les fils RSS, sont également générées.

Le système ne fournit aucun outil d’édition (on emploie l’éditeur de texte de son choix), ne gère pas le versionnage (on utilise plutôt un logiciel comme Git), ne dépend d’aucune base de données (le système de fichiers fait office de base de données). Pelican est en quelque sorte à Python ce que le populaire Jekyll est à Ruby.

Également fait avec Python, Nikola ressemble beaucoup à Pelican. Cependant, j’ai obtenu des résultats si rapides avec Pelican, dont j’appréciais particulièrement les qualités énumérées ci-après, que je n’ai pas eu à chercher plus loin :

  • Architecture logicielle simple, allant droit au but.
  • Système modulaire et extensible. Nombreuses extensions disponibles.
  • Résultat minimaliste, n’incluant ni plus, ni moins que ce que le site a besoin. On a plein contrôle sur le résultat.
  • Projet actif, bien documenté, et constamment amélioré par un grand nombre de participants.
  • Gabarits (templates) définis avec Jinja, une syntaxe plaisante, riche en fonctionnalité et utilisée dans moult logiciels.
  • Outre reStructuredText, Markdown et HTML, plusieurs formats d’entrée sont offerts à travers des extensions.
  • Outil de migration de contenus.

Construire avec Pelican

En suivant les instructions de démarrage de Pelican, en m’inspirant de d’intégrations graphiques existantes (ou thèmes), puis en explorant les options de migration, il ne m’a suffit que de quelques heures de travail pour bâtir un prototype fonctionnel qui incluait même les contenus importés depuis Drupal !

Malgré cela, arriver au produit fini n’aura pas été plus rapide que si j’avais construit le site avec Drupal. Bâtir un thème pour Pelican demande autant d’attention que d’en créer un pour Drupal; il s’agit avant tout d’un travail sur les codes HTML et CSS. Puisque je souhaitais une présentation personnalisée pour le site plutôt que d’utiliser un thème existant, c’est là que mes efforts se sont concentrés.

En revanche, sur le plan technique je suis plus satisfait du résultat. Voyez le code source de la page, regardez-moi ce schéma HTML, ces éléments sectionnels sémantiques et bien titrés, cette absence de classes superflues ! Pelican donne plein contrôle sur tout le balisage.

Pour produire le même balisage avec Drupal, il m’aurait fallu « déconstruire » une grande partie du système pour supplanter de nombreux gabarits et fonctions de thème par défaut, un travail bien plus long et fastidieux. Travailler efficacement avec Drupal requiert d’accepter, dans une certaine mesure, le balisage et la structure de gabarits et de fonctions de thème qui sont fournis.

Avec Pelican, la structure imposée est minimale. On crée un gabarit pour chaque type de page (index, article, page, catégorie, etc.) et dans chaque gabarit on dispose de toutes les variables utiles. À l’intégrateur de prendre soin de définir une structure hiérarchique de gabarits, de faire des généralisations, et seulement si cela lui est utile. C’est là, d’ailleurs, que brillent les mécanismes d’héritage, d’inclusion et de macros de Jinja.

Le graphisme de mon site est délibérément très simple. En effet, parce que le graphisme n’est pas ma spécialité, j’évite de trop en faire pour ne pas me piéger ! Cependant Pelican et Jinja se prêtent parfaitement à des structures plus complexes.

Choisir les composantes

Avec tout le contrôle que nous confère Pelican viennent les responsabilités. Les normes web évoluent constamment et nul ne peut prétendre tout connaître et tout maîtriser parfaitement. Il convient alors d’éviter de réinventer la roue et d’incorporer les meilleures pratiques, en choisissant des composantes reconnues.

Ainsi, pour structurer le HTML et le CSS de mon site, j’ai sélectionné les principales composantes suivantes, avec lesquelles j’étais déjà familier à travers nombre de projets web :

En ce qui a trait à la fonctionnalité, je me suis arrêté notamment sur :

  • Extensions Pelican :

    • Assets, dont je me sers surtout pour lancer automatiquement Compass dans le processus de génération du site et pour versionner automatiquement les liens des feuilles de style et ainsi assurer, en cas de mise à jour du code CSS, que la plus récente version soit préférée à celle de la cache du fureteur (i.e. dispositif de cache busting).
    • Neighbors, pour les liens vers les articles précédent et suivant.
    • Related posts, pour fournir la liste des articles similaires.
    • Share post, pour fournir les liens de partage sur les réseaux sociaux. Cette extension évite les habituels widgets « espions », de sorte que Twitter et Facebook ne sauront pas que vous avez visité mon site !
  • Disqus, pour la prise en charge des commentaires. N’oublions pas que mon site est purement statique et n’a pas de base de données ! J’ai donc externalisé cette fonction dynamique à l’aide du populaire Disqus.

  • Brace Forms Formspree, pour la prise en charge du formulaire de contact, autre fonction impossible avec un système purement statique. J’apprécie grandement le minimalisme de ce service, qui ne se contente que de transmettre les soumissions par courriel à partir d’un formulaire qu’on peut construire en un clin d’œil.

    Mise à jour (2015-01-04) : Formspree remplace Brace Forms. Son code source est désormais ouvert, permettant à quiconque le désire d’héberger lui-même le service et d’en modifier le fonctionnement. On découvre par la même occasion que le système est bâti avec Python, Flask et Redis !

  • HTML5 Boilerplate Server Configs, pour tirer parti de réglages experts aidant à maximiser la performance et la sécurité du serveur web.

Migrer les contenus depuis Drupal

Dans un projet de refonte, la migration des données est souvent l’étape qu’on aborde avec le plus d’appréhension… Cette fois, grâce aux outils disponibles tant sous Drupal que sous Pelican, la migration s’est avérée être un jeu d’enfant.

Mon site tournait encore sur une très vieille version de Drupal. Il y a environ trois ans, j’avais migré ses données à Drupal 7 en vue d’une refonte du site, refonte que je n’ai finalement jamais vraiment démarrée. Comme aucun contenu n’avait été créé sur le site depuis lors, cette version Drupal 7 du site pouvait servir de source pour la migration, l’avantage étant de pouvoir mettre à contribution des modules Drupal à jour.

J’ai donc installé la dernière version de Views, activé la vue Front page, puis modifié les réglages de l’affichage RSS de cette vue pour éliminer la limite du nombre d’éléments et montrer tous les contenus publiés (pas seulement ceux promus dans la page d’accueil). Le fil RSS de l’accueil incluait désormais tous les articles du site et j’ai sauvegardé son contenu dans un fichier.

Puis j’ai lancé la commande suivante :

pelican-import --feed -m rst -o DESTINATION SOURCE.xml

Ici, pelican-import est une commande fournie avec Pelican, DESTINATION le répertoire de sauvegarde des contenus et SOURCE.xml le fichier source, de format RSS, découlant de ma vue.

L’outil a alors fait une admirable conversion, en format reStructuredText, de tous les articles du fichier source. Seules quelques petites corrections manuelles ont été requises dans certains fichiers pour nettoyer des éléments non pris en charge par la conversion, dans mon cas des balises <div> superflues, pour réparer les références aux images incorporées aux contenus, ainsi que pour harmoniser l’URL de chaque article avec son URL original.

J’ai ensuite copié tout le contenu du répertoire « fichiers » du site dans le répertoire des fichiers statiques de Pelican. Une dernière commande (make html) pour demander à Pelican de générer le site et voilà, migration achevée !

Bloguer comme un geek

Je doute que mon nouveau site fasse soudainement de moi un blogueur prolifique, mais au moins, lorsque j’écrirai, ce sera dans l’environnement technique qu’apprécie le geek en moi : l’éditeur de texte puissant que j’utilise pour la programmation et que j’ai personnalisé au fil du temps, la gestion des versions avec Git, l’opération rapide à la ligne de commande, la manipulation facile de fichiers textes avec des outils Unix ou des scripts ad-hoc.

On l’a vu, je peux négliger mon site parfois longtemps, trop longtemps ! Maintenant que j’ai éliminé, d’une part, les risques de sécurité inhérents à une exécution dynamique et, d’autre part, les dépendances envers des briques logicielles complexes pour l’hébergement, on pourrait dire, sur le strict plan technique, que ce site pourrait probablement rester inchangé pour un nouveau cycle outrageusement long ! Mais mon intention n’est pas d’en faire une archive statique. Au contraire, j’espère que le terme « statique » ne décrira que sa méthode de livraison du contenu ! Je mise sur la simplicité du nouveau système et le plaisir lié à sa programmation en Python pour m’amener à le faire évoluer occasionnellement, par raffinements successifs, plutôt que le laisser stagner jusqu’à une éventuelle refonte brutale.

À suivre !

Commentaires