Using Web Mentions in a static site (Hugo)

Mon blog est un site entièrement statique, construit avec Hugo et hébergé avec Zeit. C'est une excellente solution pour moi, un simple blog a un processus de déploiement assez simple et son chargement est extrêmement rapide.

Les sites générés statiquement présentent certains inconvénients, le plus important étant lorsque vous avez besoin d'intégrer quelque chose de dynamique dans votre page (commentaires, par exemple). Ne pas être en mesure d'héberger facilement du contenu dynamique signifie que vous finirez par vous fier à du code JavaScript tiers qui obtiendra alors un accès complet à votre page. Vous ne saurez pas ce qu'il fait. Cela peut être le suivi de vos utilisateurs ou le ralentissement de votre page. charge.

J'ai récemment enlevé mon widget de commentaire actuel (Disqus) du chemin de rendu critique en ne le chargeant que lorsque l'utilisateur fait défiler les commentaires (à l'aide de IntersectionObserver ). IntersectionObserver que ce soit une solution raisonnable aux problèmes de performances de chargement et de suivi, je souhaitais en fait le supprimer. Disqus tous ensemble.

Entrez la spécification Webmention . Webmention est une spécification qui décrit comment un auteur de site peut être contacté lorsqu'un autre site "mentionne" (ou aime) le contenu de votre site. Cela permet en fin de compte de mettre au point une méthode décentralisée pour découvrir le contenu qui renvoie à votre site, en apportant une valeur ajoutée et une visibilité.

La spécification webmention ne décrit aucun format de données qui devrait être utilisé pour communiquer ce que le "site de mention" a dit, il vous reste à analyser à l'aide de microformats standard ou d'autres mécanismes permettant de comprendre le contenu de la page. C’est formidable, mais j’estime que cela conduit à des services centralisés tels que webmention.io fournissent l’infrastructure indispensable pour tirer le webmention.io parti de la page.

J'ai aimé l'idée d'utiliser Webmention, mais cela nécessite une configuration côté serveur pour obtenir (et éventuellement stocker) des notifications lorsque quelqu'un mentionne votre site. Ce n'est pas toujours possible avec un constructeur statique comme celui que j'ai sur mon site. Le reste de cet article décrira rapidement comment j'ai hébergé des mentions J'aime, des mentions et des reprises sur mon build Hugo hébergé sur Zeit.

étape - trouver un hub Webmention

J'ai trouvé webmention.io et ça fait l'affaire. Il gère les pingbacks entrants et les mentions, il va également valider que le site appelant est en train de créer un lien vers votre contenu et enfin, il analysera les données en dehors de la page afin que vous compreniez le contexte.

Webmention.io validera que le site vous appartient par le biais d'un processus d'authentification ouvert (il était soigné, il recherche rel = me qui pointe vers un fournisseur d'authentification)

étape - indiquez aux pages que vous pouvez gérer les mentions

C’est aussi simple que d’ajouter les deux balises link suivantes

<link rel="webmention" href="https://webmention.io/paul.kinlan.me/webmention">
<link rel="pingback" href="https://webmention.io/paul.kinlan.me/xmlrpc">

étape - intégrez l’API webmention.io dans votre site

Vous avez deux options ici, vous pouvez ajouter un widget sur votre page qui appellera l'API webmention.io ou intégrer l'API webmention.io dans votre étape de construction. Je voudrais aussi peu de JS hébergé par une tierce partie que possible, alors j'ai choisi ce dernier. J'ai intégré des webmentions dans mon processus de déploiement.

J'utilise Hugo parce que la construction est rapide et, dans cet esprit, je devais trouver un moyen d'intégrer de manière optimale l'API Webmention dans Hugo. La contrainte majeure était de ne pas appeler le point de terminaison de l'API pour chaque page de mon site. J'ai beaucoup de pages et pas encore beaucoup de commentaires.

Heureusement, le site Webmention.io fournit un point de terminaison pratique qui vous permettra de recevoir toutes les mentions de votre domaine. Le malheur est que ce fichier contient une entrée pour chaque action effectuée contre votre site.

Hugo a également la notion de fichiers de données pouvant être insérés directement dans le modèle pour une page donnée. Vous devez donc mapper le fichier de données Webmention sur une nouvelle structure facilitant la lecture dans un modèle Hugo.

Le processus que j'ai choisi est présenté ci-dessous, mais le résumé consiste à transformer le tableau d'une liste d'actions en un dictionnaire d'URL contenant chacune les actions exposées par l'API (telles que, republication et réponse), et la dernière étape consiste à: divisez le dictionnaire des URL en fichiers individuels nommés hachage md5 de l'URL.

"use strict";

const fs = require('fs');
const fetch = require('node-fetch');
const md5 = require('md5');

const processMentionsJson = (data) => {
  const urlData = {};
  data.children.forEach(item => {
    const wmProperty = item["wm-property"];
    const url = item[wmProperty];

    if(url in urlData === false) urlData[url] = {};
    const urlDataItem = urlData[url];

    if(wmProperty in urlDataItem === false) urlDataItem[wmProperty] = [];
    urlDataItem[wmProperty].push(item);
  });

  console.log(urlData);

  // For each URL in the blog we now have a JSON stucture that has all the like, mentions and reposts
  if(fs.existsSync('./data') === false) fs.mkdirSync('./data');
  Object.keys(urlData).forEach(key => {
    const item = urlData[key];
    const md5url = md5(key);
    console.log(key, md5url)
    fs.writeFileSync(`./data/${md5url}.json`, JSON.stringify(item));
  });
}

(async () => {
  const mentionsUrl = new URL(process.argv[2]); // Fail hard if it's not a uRL

  const mentionsResponse = await fetch(mentionsUrl);
  const mentiosnJson = await mentionsResponse.json();

  processMentionsJson(mentiosnJson);
})();

Une fois les données analysées et enregistrées correctement, il s'agit d'un processus rapide de configuration du modèle afin qu'il puisse être lu dans l'attribut Données du modèle.

{{ $urlized := .Page.Permalink | md5 }}
{{ if index .Site.Data $urlized }}
  {{ $likes := index (index .Site.Data $urlized) "like-of" }}
  {{ $replys := index (index .Site.Data $urlized) "in-reply-to" }}
  {{ $reposts := index (index .Site.Data $urlized) "repost-of"}}
  <h4>Likes</h4>
  {{ range $i, $like := $likes }}
    <a href="{{$like.url}}"><img src="{{ $like.author.photo}}" alt="{{ $like.author.name }}" class="profile photo"></a>
  {{end}}

  <h4>Reposts</h4>
  {{ range $i, $repost := $reposts }}
    <a href="{{$repost.url}}"><img src="{{ $repost.author.photo}}" alt="{{ $repost.author.name }}" class="profile photo"></a>
  {{end}}

  <h4>Comments and Replies</h4>
  {{ range $i, $reply := $replys }}
    <a href="{{$reply.url}}"><img src="{{ $reply.author.photo}}" alt="{{ $reply.author.name }}" class="profile photo"></a>
  {{end}}
{{end}}

Si tout se passe bien, vous devriez voir des icônes au bas de la page qui sont de vraies personnes qui interagissent avec le site.

Étape 4 - publiez le site lorsque des commentaires apparaissent

Bien que les étapes ci-dessus me permettent d'agréger les mentions et de les rendre dans la sortie des sites, je dois tout de même m'assurer que le site est reconstruit régulièrement pour que les commentaires soient publiés.

J'ai choisi d'utiliser un simple service cron qui appellera l'API de déploiement de Zeit pour forcer un nouveau dépôt du site toutes les heures environ.

Paul Kinlan

Trying to make the web and developers better.

RSS Github Medium