В отличие от прошлого года, в 2019 я не планировал никаких сложных движений с сайтом, что, впрочем, не помешало ему измениться на полторы сотни коммитов.
Jekyll config для стейджинга
1 По дефолту Джекил не генерирует посты из папки _drafts
Во время деплоя на mirror.snnkv.com, который я использую для стейджинга, и экспериментов, было неудобно пользоваться основным конфигом Джекила. Например, был период, когда мне хотелось видеть там все имеющиеся записи вместе с черновиками1. Или вот более приземлённый пример: на основном сайте установлен скрипт Гугл Аналитики. Очевидно, что на зеркале ему не место, а значит два сайта должны быть сгенерированы по-разному.
Джекил позволяет использовать несколько разных конфигов одновременно. Для этого сборку нужно запустить так: jekyll build --config my_rad_config.yml
. Кроме того для изменений настроек сборки можно использовать переменные окружения типа JEKYLL_ENV=stage
. Всё это хорошо описано в документации а в интернетах есть море примеров.
2 А позже и третий и четвёртый
Из-за того что CI итак использовал разные пайплайны для раздельной сборки основного сайта и зеркала, внедрить второй2 конфиг было не сложно.
Обновления во Front Matter
У постов обновилась секция Front Matter в которой хранятся метаданные о публикации. Я добавил туда поля date
и updated
.
Раньше поле date
было привязано к названию файла поста и мы решили от этого избавиться. А поле updated
вообще было строкой вида «Обновлено в июне 2017», которую нужно было заполнять руками допуская ошибки. Теперь оба поля это дата в формате YYYY-MM-DD. В целом мета для этого поста в 2019 выглядела так:
---
layout: post
category: articles
title: Как я пользовался Jekyll в 2019
description: Технические детали о том, что нового добавлено на сайт в 2019 и что из него, наконец-то, убавлено
date: 2019-08-22
updated: 2021-01-10
tags: [Этот сайт]
assets: /assets/posts_data/2019-08-22-site-state-2019
background: /assets/posts_data/2019-08-22-site-state-2019/title-back.jpg
---
<!-- тут md и html -->
Ещё в какой-то момент мне приспичило опубликовать несколько страниц на английском языке чтобы дать на них ссылку ограниченному кол-ву посетителей. Казалось бы ничего сложного: просто заверстай страницу и закрой basic auth паролем. Но страница-сирота с которой нельзя никуда уйти будет рендериться с русскими хлебными крошками и русским же подвалом.
Пришлось сделать несколько твиков в шаблоне, а во Front Matter появилось необязательное поле language
. Из-за того, что Джекил знает английские названия месяцев, для их русификации пришлось сделать файл-словарик /_data/ru-months.yml
, а в шаблоне использовать вот такой костыль:
{% if page.language %}
<h6 title="Published on {{ page.date | date: '%Y-%m-%d' }}, updated on {{ page.updated | date: '%Y-%m-%d' }}">
{{ page.date | date: "%B %Y" }}</h6>
{% else %}
<h6 title="Опубликовано {{ page.date | date: '%Y-%m-%d' }}, обновлено {{ page.updated | date: '%Y-%m-%d' }}">
{% assign m = page.date | date: "%-m" | minus: 1 %}
{{ site.data.ru-months.months[m] }} {{ page.date | date: "%Y" }}</h6>
{% endif %}
Краудсорсинг ошибок
С самого первого дня я планировал добавить на сайт краудсорсинг ошибок и опечаток. Макс даже нарисовал для этого попап. Возможно, вы видели такую фичу на старых сайтах из 90х, хотя некоторые современные ответственные редакторы используют эту функцию до сих пор. Например, штука есть на сайте Медузы.
Работает это так. Посетитель увидев ошибку в тексте может выделить её, а потом по нажатию Ctrl+Enter
заслать редактору. Я понимаю, что для таких выкрутасов нужны по меньшей мере компьютер с клавиатурой, а их в мире осталось полтора десятка ведь все смотрят в интернет из смартфонов.
Я часто пользуюсь этой фичей сам и она мне нравится. Это быстро и бесплатно. Это возможность нести ответственность за текст, а не валить в интернет невычитанные посты в которых даже падежи не согласованы. Ошибаются все. Исправляют единицы.
Отправить тоже можно по Enter
Помимо выделенного текста скрипт захватывает некоторую окрестность чтобы можно было оценить контекст. Есть необязательный эдит с комментарием куда можно написать что-то типа «Капец ты тупой, тут сложносочинённое же!».
Я долго думал как вообще обойтись без серверного кода, но потом всё-таки написал крохотный репитер, который после буферизации присылает мне все эти сообщения в Телеграм.
Планирую не ломать пока работает.
Gulp для сборки
3 На этот момент на сайте уже была пара внутренних страниц которые весили по 80-100 мегабайт из-за фоток и гифок.
Локальная сборка сайта с каждым коммитом становилась всё сложнее. Количество ассетов росло, а хранить их в репозитории с исходниками становилось всё накладнее. Было очевидно, что в будущем ассеты куда-то переедут и, скорее всего, станут responsive3, а значит их количество запросто утроится. Кроме того responsive картинки придётся генерировать автоматически и кешировать. А где кеш, там и его менеджмент.
В общем, локальное выполнение jekyll build
уже выглядело как прошлый век даже не смотря на возможность настраивать сборку конфигами. Было решено освоить Gulp. Во всяком случае этот подход должен был хорошо масштабироваться и иметь громадный задел для будущих фичреквестов.
Первые таски в Gulp дублировали то, что итак происходило на CI:
- сборка сайта с production или staging конфигом
- проверка получившихся файлов htmlproofer’ом
- подпись версии тоже переехала в gulp task из git pre-commit скрипта.
% gulp --tasks
[20:19:05] Tasks for ~/Github/snnkv.com/gulp/gulpfile.js
[20:19:05] ├── scale Оптимизирует разрешение всех картинок
[20:19:05] ├── cp:all Копирует все ассеты прямо /_site/assets/
[20:19:05] ├── cp:cache-to-assets-all Копирует кэш в папку ассетов (нужна для отладки)
[20:19:05] ├── cp:orig-to-cache-non-pics Копирует ассеты, которые не являются картинками в кэш
[20:19:05] ├── cache:clear Чистит кэш
[20:19:05] ├── serve:wo-assets jekyll serve без ассетов
[20:19:05] ├── clean jekyll clean
[20:19:05] ├── build:default jekyll build с дефолтовым конфигом
[20:19:05] ├── build:dev jekyll build с dev конфигом
[20:19:05] ├── proofer Запускает htmlproofer по готовой статике из папки /_site
[20:19:05] ├── symlink:orig Устанавливает симлинк на оригинальные ассеты
[20:19:05] ├── symlink:cache Устанавливает симлинк на ассеты из кэша
[20:19:05] ├─┬ serve:orig
[20:19:05] │ └─┬ <series>
[20:19:05] │ ├── clean
[20:19:05] │ ├── build:dev
[20:19:05] │ └─┬ <parallel>
[20:19:05] │ ├── serve:wo-assets
[20:19:05] │ └── symlink:orig
[20:19:05] ├─┬ serve:dev
[20:19:05] │ └─┬ <series>
[20:19:05] │ ├── cache:clear
[20:19:05] │ ├── scale
[20:19:05] │ ├── cp:orig-to-cache-non-pics
[20:19:05] │ └─┬ <parallel>
[20:19:05] │ ├── serve:wo-assets
[20:19:05] │ └── symlink:cache
[20:19:05] └─┬ build-n-proof
[20:19:05] └─┬ <series>
[20:19:05] ├── clean
[20:19:05] ├── build:default
[20:19:05] └── proofer
Главный кайф Gulp — акцент на атомарности заданий. Я сделал много мелких тасков, которые легко было комбинировать превращая в совершенно разные пайплайны.
Автоподстановка имён файлов в VS Code
VS Code мой «редактор по дефолту». Провожу в нём очень много времени втч потому что любую фигню там можно автоматизировать стандартными средствами, а что нельзя, то уже автоматизировано плагинами. Правда, в этот раз пришлось написать свой собственный велосипед.
Долгое время я мирился с кривым процессом подготовки картинок для постов. В простом случае процесс выглядел так:
- Найти подходящую картинку или фотку
- Закинуть её в Photoshop для редактирования, кадрирования и пр.
- Сохранить результат в папку ассетов соответствующую посту
- Вставить название в html-сниппет внутри поста.
Последние два действия требовали какого-то нечеловеческого фокуса и длительного возюканья мышкой. Выбирать папку для сохранения картинки долго — она в дебрях репозитория. Потом файлу ещё нужно придумать имя. Раньше я вообще включал разрешение картинки прямо в имя, т.е. оно получалось сложным. И после всего нужно было не забыть вовремя скопировать название этого файла чтобы вставить в пост в виде {{page.assets}}/cool_story900x600.jpg
.
В потоке, когда нужно подготовить 10 картинок, процесс работает почти без сбоев, но как только нужно что-то быстро поправить перед пушем, то одно только открытие нужных дирректорий вызывало у меня скрежет зубов.
4 Он был не сам длинным но я всегда жутко бесился забыв скопировать название файла вовремя.
Для упрощения последнего шага4 я написал не сложный плагин который получал из Front Matter поста значение переменной {{page.assets}}
в которой хранился путь до папки с картинками конкретного поста. Потом через механизмы IntelliSense я получал список файлов в этой папке, которые мог легко подставить в нужное место. Вот как это работает на практике.
Я не публиковал этот плагин.
Переезд на Gitlab CI
В начале года я занимался наведением порядка в подписках и решил отправить GitHub под нож. Во многом из-за того, что на тот момент у меня уже была история тёплых отношений с Gitlab. Поэтому сайт переехал туда.
Вместе с сайтом на Гитлаб должен был перебраться весь CI/CD. Не то, чтобы мне чем-то сильно не нравился Buddy.Works который я использовал до этого, скорее просто хотелось посмотреть на альтернативы.
Я мигрировал пайплайны две недели. Настройка сильно отличалась от галочек и кнопочек Buddy. В Гитлабе нужно было писать какие-то конфиги и читать документацию. Зато, в отличие от Buddy, там были такие крутые штуки как кеширование артефактов и собственные репозитории с пакетами для Node и Ruby, что, в теории, должно было ускорить сборку.
Сама схема работы по сравнению с прошлым годом не сильно поменялась и теперь выглядит примерно так:
Окончательно переехав я сделал два вывода:
- Скорость сборки увеличилась лишь незначительно
- Интеграция CI с другими узлами Гитлаба — уберфича. Так и должно быть.
- На Buddy я уже не вернусь. Gitlab CI предоставлял необычную гибкость в настройке.
- Gitlab CI отлично масштабируется. Если сайт сильно увеличится, то я всё ещё смогу пользоваться этим CI через self-hosted runners.
Новая шапка для постов
Уже в 2018 мы нашли уязвимое место шаблона постов — заглавная картинка плохо работала с широченными мониторами. Её приходилось делать с нестандартным соотношением сторон типа 5:1. Кадрировать туда что-то было сложно.
В 2019 Макс перерисовал шаблон для десктопа и для мобильной версии. Теперь картинка не упиралась в окно справа и слева, а заголовок и сниппет поста стояли отдельно, выше картинки.
Хлебные крошки и поиск тоже незначительно изменились.
Остальное
- В 2019 Гриша перевёз стили на SASS. Джекилл по-умолчанию поддерживает их из коробки, поэтому это был, скорее, вопрос оптимизации.
- Появилась возможность ссылаться на подзаголовки вплоть до третьего уровня. Как и везде для этого нужно навести курсор на подзаголовок и кликнуть на появившуюся иконку звена.
- Font Awesome был бесжалостно выпилен. А две с половиной иконки, которые оттуда использовались, были заменены на статично подключенные
.svg
- Гриша починил поиск при помощи смешного костыля из регулярных выражений. Теперь блок с похожими постами специально помечался в коде страницы. Сама страница передавалась в lunr.js через фильтр, который этот кусок вырезал. Нет ссылок — нет проблем.
That’s all, folks.
⚠️ Каменты в режиме эксперимента. Нужна регистрация на GitHub и необходимо дать разрешение боту Giscus. Если это неприемлемо, можно комментировать прямо на GitHub.