Почему стандартные плагины jekyll далеки от идеала

В этой заметке я не буду приводить полный код для всех компонентов, только дам сниппеты и подсказки, на что стоит обратить внимание при сборке сайта на jekyll.

Jekyll Structured Data and sitemap.xml 1535x697 jekyll-structured-data-sitemap-and-nginx.png
Jekyll Structured Data and sitemap.xml

Время модификации файла

Каждая страница имеет как минимум три точки отображения временной отметки в разных файлах, элементах страницы или ответе сервера, и все они должны быть одинаковыми.

  • ld+json "dateModified": "2025-03-07T15:43:42+00:00"
  • sitemap <lastmod>2025-03-07T15:43:42+00:00</lastmod>
  • headres last-modified: Fri, 07 Mar 2025 15:43:42 GMT

Начнём с sitemap.xml, в стандартном jekyll-sitemap, для страниц page, которые на этом сайте используются для вывода collections, время изменения берётся из времени изменения файла.
То есть, для страницы https://webart4.me/en/linux/blog/
будет установлено время изменения файла /categories/en/blog.md:
{{ page.last_modified_at | date_to_xmlschema }}, а это не совсем правильно.

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

Поэтому, выбираем все публикации для данной локали, потом те, которые относятся к этой категории, сортируем по дате, выбираем самую новую.

1
2
3
4
5
6
{% assign new_posts = site.posts | where_exp:"post", "post.locale == 'en'" | where_exp:"post", "post.categories contains 'blog'" | sort: "last_modified_at" | reverse | first | default: "notfound" %}
{% if new_posts != "notfound" %}
    <lastmod>{{ new_posts.last_modified_at | date_to_xmlschema }}</lastmod>
{% else %}
    <lastmod>{{ page.last_modified_at }}</lastmod>
{% endif %}

Соответственно, для генерации Structured Data будет такая же логика.

Ответ сервера Last-Modified

Тут уже интересней.

При пересборке сайта jekyll build --destination файлы будут обновлены. Даже если использовать --incremental, всё равно не получится перенести корректные атрибуты файлов, учитывая, что для некоторых файлов они должны иметь генерированные значения.

Для этого используем изящный и простой скрипт, который должен запускаться после каждого деплоя на сервере.

nano touch_files.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash

OPTS=`getopt -o D: --long dir: -n 'parse-options' -- "$@"`
if [ $? != 0 ] ; then
  echo "Failed parsing options." >&2
  exit 1
fi
eval set -- "$OPTS"
while true; do
  case "$1" in
    -D | --dir )                DIR="$2"; shift 2 ;;
    -- ) shift; break ;;
    * ) break ;;
  esac
done

domain="https://webart4.me"

if [[ -f "${DIR}/sitemap.xml" ]]; then
    I=`cat ${DIR}/sitemap.xml | grep -E "<loc>" | wc -l`
    for ((i = 1; i <= "${I}"; i++)) ; do
        location=`/usr/bin/xmllint --xpath "string(//*[local-name()='url'][${i}]/*[local-name()='loc'])" ${DIR}/sitemap.xml`
        ifile="${location##$domain}"
        is_html="${ifile##*html}"
        if [[ ! -z "$is_html" ]]; then
                ifile="${ifile}index.html"
        fi
        ds=`/usr/bin/xmllint --xpath "string(//*[local-name()='url'][${i}]/*[local-name()='lastmod'])" ${DIR}/sitemap.xml`
        if [[ -f "${DIR}${ifile}" ]]; then
                printf '%s\n' "${i}   ${DIR}${ifile}"
                touch --date="${ds}" ${DIR}${ifile}
        else
                printf '%s\n' "file error   ${DIR}${ifile}"
        fi
    done
else
    printf '%s\n' "No sitemap.xml"
    exit 0
fi
1
2
/bin/bash ${path_to_script}/touch_files.sh --dir ${site_root_dir_with_sitemapxml}
  

Скрипт парсит sitemap.xml, и для всех файлов из <loc> устанавливает <lastmod>.