Using Web Mentions in a static site (Hugo)

Мой блог - полностью статичный сайт, созданный с помощью Hugo и размещенный на Zeit. Это отличное решение для меня, простой блог имеет довольно простой процесс развертывания и загружается невероятно быстро.

Статически сгенерированные сайты имеют некоторые недостатки, самый большой из которых - когда вам нужно что-то динамическое для интеграции в вашу страницу (например, комментарии). Неспособность легко разместить динамический контент будет означать, что вы в конечном итоге будете полагаться на сторонний JavaScript, который затем получит полный доступ к вашей странице, и вы не будете знать, что он делает - это может быть отслеживание ваших пользователей или замедление вашей страницы нагрузить.

Недавно я снял текущий виджет комментариев (Disqus) с критического пути рендеринга, загружая его только тогда, когда пользователь прокручивает комментарии (используя IntersectionObserver ), и хотя это было разумным решением проблем производительности и отслеживания загрузки, я на самом деле хотел удалить Disqus все вместе.

Введите спецификации Webmention . Webmention - это спецификация, которая описывает, как можно связаться с автором сайта, когда другой сайт «упоминает» (или любит) контент на вашем сайте. В конечном итоге это позволяет использовать децентрализованный метод обнаружения контента, который ссылается на ваш сайт, и, как мы надеемся, обеспечивает ценность и понимание.

Спецификация веб-упоминания не описывает какие-либо форматы данных, которые должны использоваться для передачи того, что сказал «сайт упоминания», что вам остается анализировать с использованием стандартных микроформатов или других механизмов, чтобы понять содержание страницы. Это здорово, однако я считаю, что это приводит к централизованным сервисам, таким как webmention.io предоставляющим столь необходимую инфраструктуру, чтобы вывести смысл из страницы.

Мне понравилась идея использования Webmention, но она требует настройки на стороне сервера для получения (и, возможно, хранения) уведомлений о том, когда кто-то упоминает ваш сайт, это не всегда возможно при использовании статического компоновщика, как у меня на моем сайте. Остальная часть этого поста будет быстро описывать, как я получил лайки, упоминания и репосты, размещенные на моей сборке Zego Hugo.

Шаг первый - найдите центр веб-упоминания

Я нашел webmention.io, и он делает свое дело. Он обрабатывает входящие пингбэки и упоминания, а также проверяет, действительно ли вызывающий сайт ссылается на ваш контент, и, наконец, он будет анализировать данные со страницы, чтобы вы имели некоторое представление о контексте.

Webmention.io проверит, что вы являетесь владельцем сайта через открытый процесс аутентификации (он был аккуратен, он ищет rel = me, который указывает на поставщика аутентификации)

Шаг второй - скажите страницам, что вы можете обрабатывать упоминания

Это так же просто, как добавление двух следующих тегов link

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

Шаг третий - интегрируйте API webmention.io в свой сайт

У вас есть два варианта: вы можете добавить на свою страницу виджет, который будет вызывать API webmention.io, или вы можете интегрировать API webmention.io в свой этап сборки. Я бы хотел, чтобы JS размещал как можно меньше сторонних разработчиков, поэтому я выбрал последнее. Я включил веб-упоминания в свой процесс развертывания.

Я использую Hugo, потому что сборка быстрая, и, учитывая это, мне пришлось поработать над тем, как оптимально интегрировать API Webmention в Hugo. Жестким ограничением было не вызывать конечную точку API для каждой страницы на моем сайте, у меня много страниц и еще не так много комментариев.

К счастью, сайт Webmention.io предоставляет удобную конечную точку, которая позволит вам получить все упоминания для вашего домена. Неудача в том, что этот файл содержит одну запись для каждого действия, которое было выполнено с вашим сайтом.

У Хьюго также есть понятие файлов данных, которые можно вставить непосредственно в шаблон для любой данной страницы, поэтому вам необходимо сопоставить файл данных Webmention с новой структурой, которая упрощает чтение в шаблоне Хьюго.

Процесс, который я выбрал, приведен ниже, но в итоге я превращаю массив из списка действий в словарь URL-адресов, каждый из которых содержит действия, предоставляемые API (например, repost и reply), и последним шагом является разбить словарь URL-адресов на отдельные файлы, которые названы как хэш md5 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);
})();

После того, как данные проанализированы и сохранены правильно, это быстрый процесс настройки шаблона, чтобы его можно было прочитать в атрибуте данных шаблона.

{{ $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}}

Если все идет хорошо, вы должны увидеть некоторые значки внизу страницы, которые являются реальными людьми, взаимодействующими с сайтом.

Шаг 4 - публиковать сайт при появлении комментариев

Несмотря на то, что описанные выше шаги позволят мне объединить упоминания и отобразить их в выходных данных сайтов, я все же должен убедиться, что сайт регулярно перестраивается, чтобы комментарии появлялись в открытом доступе.

Я решил использовать простой сервис cron, который будет вызывать API развертывания Zeit для принудительной повторной деполяции сайта каждый час или около того.

Paul Kinlan

Trying to make the web and developers better.

RSS Github Medium