Почему это стоит прочитать #
С прошлого разбора прошёл ровно месяц: 0.163.3 вышел 18 июня, 0.164.0 — 6 июля. После «квартала инфраструктурного взросления» с AVIF и хардненингом этот релиз выглядит скромнее: одна минорная версия, никаких громких фич.
Но два пункта в нём заслуживают внимания:
- Стили Chroma получили dark/light-пары. Подсветка кода наконец умеет жить в двух темах штатно, а не через самодельные костыли.
- Починена регрессия производительности, тянувшаяся с 0.128.0. Это не новая фича, а возврат утраченного — но на больших сайтах разница заметна.
Остальное — приятные мелочи в шаблонных функциях и один депрекейт. Breaking changes как таковых нет, обновление спокойное.
Главное за один взгляд #
Фичи:
- Dark/light-пары в стилях Chroma — подсветка синтаксиса умеет два режима; у команды
hugo gen chromastylesпоявились новые флаги. - Новые шаблонные функции:
crypto.Hash,encoding.HexEncode,encoding.HexDecode. - Опция
markup.rst.syntaxHighlight— подсветка для reStructuredText. - Поддержка цитат в Pandoc — для тех, кто держит библиографию.
- Вложенные пути в layouts для
Page.Render. - Фикс регрессии производительности из 0.128.0 — обсуждение на Discourse тянулось долго.
Депрекейт:
resources.PostProcessобъявлен устаревшим в пользуtemplates.Defer(issue #15086).
Мелочи, которые могут задеть:
- Поиск имени шаблона стал регистронезависимым (#15057).
.Renderтеперь возвращает ошибку, если шаблон не найден (#15052) — раньше молча отдавал пустоту.IsSetвключает ключ в предупреждение о неподдерживаемом типе.
Dark/light в Chroma 🌗 #
Главная фича релиза — и, пожалуй, самая недооценённая.
Раньше стиль подсветки в Hugo был один на весь сайт: в hugo.toml задавался markup.highlight.style, и всё. Если сайт умеет переключаться между светлой и тёмной темой, приходилось выкручиваться: генерировать два CSS-файла через hugo gen chromastyles, руками оборачивать их в медиа-запросы или классы, следить за синхронизацией.
Теперь Chroma внутри Hugo знает про парные режимы, а у hugo gen chromastyles появились флаги для генерации нужного варианта. Смысл простой: светлая и тёмная схемы подсветки — это не два несвязанных стиля, а пара, и Hugo теперь так к ним и относится.
Что это значит для нашего блога. Прямое попадание. Переключатель дня и ночи здесь работает на JS с сохранением выбора в localStorage — то есть тема меняется без перезагрузки, и подсветка кода должна меняться вместе с ней. Сейчас в конфиге один [markup.highlight] на оба режима, и в тёмной теме блоки кода выглядят компромиссно. Это следующий пункт в списке доработок: сгенерировать пару стилей и подцепить их к тому же переключателю. В этот заход не делаю — обновление и так вышло насыщенным, — но фича переехала из «знать» в «внедрять».
Регрессия производительности: возврат утраченного ⚡ #
Незаметная, но приятная часть. В 0.128.0 (это июль 2024-го) в сборку просочилась регрессия, из-за которой большие сайты собирались медленнее. Симптом обсуждали на Discourse больше года, и вот в 0.164.0 его закрыли.
Ремарка из release notes честная: эффект заметен в первую очередь на крупных сайтах. Наш блог — около сотни страниц, и на таком объёме разница в пределах шума. Но сама история поучительна: регрессия прожила полтора года и полтора десятка релизов, потому что на маленьких сайтах её просто не видно.
Новые функции: crypto.Hash и hex 🔧 #
Три новые шаблонные функции:
{{ crypto.Hash "sha256" "текст" }}
{{ encoding.HexEncode "привет" }}
{{ encoding.HexDecode "d0bfd180d0b8d0b2d0b5d182" }}crypto.Hash принимает алгоритм явным параметром — удобнее, чем существующие md5/sha1/sha256 по отдельности. Практический сценарий — стабильные идентификаторы: захешировать путь или содержимое и получить детерминированный ключ для кэша, якоря или имени файла.
Hex-функции закрывают давнюю мелочь: base64 в шаблонах был, а hex приходилось изображать вручную.
Для нашего блога — пока в копилку. Ни одного места, где это было бы нужно прямо сейчас, нет.
Депрекейт resources.PostProcess ⚠️ #
Единственное, за чем стоит следить.
resources.PostProcess использовался для отложенной обработки ресурсов — классический сценарий — PurgeCSS/Tailwind, когда нужно узнать финальный HTML, чтобы вычистить неиспользуемые классы. Теперь рекомендуется templates.Defer, механизм более общий и предсказуемый.
Нас не задевает: проверил layouts/ и themes/ — resources.PostProcess не используется нигде. CSS через Hugo Pipes с Tailwind мы не собираем, а Pagefind живёт отдельным npm-инструментом и к ресурсной цепочке отношения не имеет.
Если у вас Tailwind в Pipes — это первое, что нужно проверить перед обновлением: депрекейт пока не ломает, но направление задано.
Осторожно: .Render теперь возвращает ошибку
#
Мелочь из списка изменений, которая может неприятно удивить. Раньше .Render с несуществующим шаблоном молча отдавал пустую строку — и сайт собирался, просто без куска контента. Теперь он возвращает ошибку, то есть сборка упадёт.
Формально это исправление, а не breaking change: молчаливая пустота — плохое поведение. Но если у вас в шаблонах есть вызов .Render с опечаткой в имени, который «работал» годами, — обновление его вскроет. Заодно поиск имени шаблона стал регистронезависимым, так что часть таких опечаток теперь, наоборот, начнёт находиться.
Инфраструктура: заодно поменяли базу образа 🐳 #
Здесь стоит рассказать про то, что к самому Hugo отношения не имеет, но всплыло при обновлении.
Блог собирается в собственном Docker-образе, куда запечены Hugo Extended, Node и Pagefind. Пошёл поднимать версию Hugo — и обнаружил, что база образа node:20-bookworm-slim достигла EOL 30 апреля 2026. То есть почти три месяца образ жил без обновлений безопасности базового слоя.
Node здесь нужен ровно для одного — установить Pagefind. Поэтому смена мажора малорискованная, и база переехала сразу на Node 24 (LTS, поддержка до апреля 2028). Итоговый образ:
hugo v0.164.0+extended linux/amd64
node v24.18.0
pagefind 1.5.2Мораль простая и не новая: следите не только за приложением, но и за базовым слоем. Версию Hugo видно в каждом релизном посте, а FROM node:20 тихо стареет в первой строке Dockerfile, пока про него не вспомнишь.
Отдельная заметка на будущее — образ до сих пор собирался руками, поэтому и отстал. Правильный путь: собирать его в CI при изменении Dockerfile. У сборки на нашем раннере есть нюанс — он живёт в LXC-контейнере, где docker build не может применить AppArmor к промежуточным RUN-контейнерам и падает. Обходится это kaniko: он собирает образ в userspace, без демона Docker и вложенных контейнеров. Тот же приём уже используется для других наших образов.
Что это значит для нашего блога #
- Chroma dark/light — самая полезная фича релиза именно для нас, ложится на существующий переключатель темы. В работу.
- Фикс производительности — приятно, но на сотне страниц незаметно.
- Депрекейт
PostProcess— не задевает, проверено. .Renderс ошибкой — не задевает, но стоит держать в голове.- Обновление базы образа с Node 20 на Node 24 — по факту важнее самого апдейта Hugo.
Чек-лист обновления ✅ #
Обновление спокойное. С 0.163.x на 0.164.0 идти можно без подготовки: breaking changes нет, депрекейт один.
Если используете
resources.PostProcess(обычно это Tailwind/PurgeCSS в Pipes) — запланируйте переход наtemplates.Defer:grep -rn 'resources.PostProcess' layouts/ themes/Если в шаблонах есть
.Render— проверьте имена шаблонов: теперь несуществующий шаблон роняет сборку, а не молчит.Если у сайта есть тёмная тема — посмотрите на парные стили Chroma, это заметное упрощение по сравнению с самодельными решениями.
Проверьте базовый слой сборочного образа, а не только версию Hugo. Node 20 в EOL с 30 апреля 2026:
grep -n '^FROM' Docker/DockerfileСтандартный прогон и сверка предупреждений до и после:
hugo --minify --gc
Итог 🧠 #
0.164.0 — релиз-передышка после насыщенного квартала. Одна по-настоящему полезная фича (парные стили Chroma), одно давно ожидавшееся исправление (регрессия скорости из 0.128.0), горсть новых шаблонных функций и один аккуратный депрекейт.
Обновляться стоит: рисков практически нет, а dark/light-подсветка снимает целый класс костылей для сайтов с переключателем темы.
Но главный вывод этого обновления оказался не про Hugo. Версию генератора видно в каждом релизном посте, а базовый слой образа стареет молча — и именно он оказался просроченным на три месяца, а не Hugo, отставший на одну минорную версию.
Источники #
- Релиз 0.164.0: gohugoio/hugo v0.164.0
- Режимы стилей подсветки: gohugo.io/quick-reference/syntax-highlighting-styles/#modes
crypto.Hash: gohugo.io/functions/crypto/hash/encoding.HexEncode: gohugo.io/functions/encoding/hexencode/- Обсуждение регрессии производительности: discourse.gohugo.io
- График поддержки Node.js: endoflife.date/nodejs