Недавно я переместил свой личный веб-сайт на Hugo, и переход с Jekyll был в основном приятным. Я получил массу улучшений во время сборки. Но что мне не понравилось, так это документация Hugo. Все основано на идее, что вы установите Hugo, создадите новый сайт, а затем добавите тему. Вот где начинается проблема. Мне не нужна стандартная тема, в конце концов, это мой личный веб-сайт, так что это должно быть моим выражением, верно? Что ж, мне посчастливилось поймать Хуэй Цзин в доброжелательном, слегка скучающем настроении. Она создала для него весь собственный CSS с фантастическим макетом Masonry.

Но это означало, что с этого момента документы Хьюго были в основном бесполезны. Они предназначены для того, чтобы помочь вам разработать тему или изменить ее, чтобы достичь чего-то нового. Мой веб-сайт Hugo изначально был не очень сложным, поэтому, следуя по стопам Хуэй Цзина, мы заставили его работать без документации. Теперь, когда MVP выпущен в течение нескольких месяцев, я продолжаю находить небольшие вещи, которые можно улучшить. Или, если вы посмотрите на мои оценки web.dev, не так уж и мало. 😏

До

У меня было изображение обложки в передней части публикации под списком images, потому что это был способ Хьюго автоматически сделать это изображение социальной картой Twitter. Я, будучи ленивым, посчитал это выигрышем. Мои изображения также хранились в папке static/, потому что это имело смысл? Я имею в виду, что изображения - это не совсем контент или активы, верно? Оказывается, это неправильно, но об этом позже.

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

![I wish all my images had alt text 🤦‍♂️](/image.png)

С макетами тут возникли сложности. Технически передний план images - это массив, даже если он когда-либо имел только один элемент. Это означало, что мне приходилось циклически перебирать эти элементы, когда я отображал их на list макетах. Или получите элемент с индексом 0. Так что в итоге код выглядел немного неаккуратно.

<img class="post-image" src="{{ range .Params.images }}{{ . }}{{ end }}" alt="{{ .Title }}" />

У этого подхода было несколько проблем.

  1. Я был слишком ленив, чтобы изменить размер всех изображений для макета list, поэтому большинство из них были довольно большими и загружались сразу на главную страницу. Медленно было мягко сказано.
  2. Я не мог беспокоиться об изменении размера изображений несколько раз, чтобы сделать изображения адаптивными. В идеале 3–4 раза. Отсюда и ужасный результат на Lighthouse.

Хотя, похоже, в конце туннеля был свет. Просматривая документы, казалось, что в Hugo есть что-то под названием Обработка изображений, и это должно было помочь решить все мои проблемы. Я мог изменять размер своих изображений во время сборки, сжимая их и изменяя качество кодирования. Все это звучало как легкое средство от моей лени. За исключением того, что документы немного тонкие, и они бесполезны для веб-сайта без темы Hugo. Я пробовал это дважды, но безуспешно, но похоже, что третий раз - прелесть.

Как добавить обработку изображений в Hugo

Первое, что я сделал неправильно, это то, что изображения были в папке static. Обработка изображений в Hugo работает с ресурсами, и для ее работы изображение должно быть либо ресурсом страницы, либо ресурсом. Ресурсы страницы должны находиться в той же папке, что и файл разметки, так что об этом не могло быть и речи. Было слишком много изображений, которые нужно было переместить, и слишком много путей, которые нужно было изменить в каждой статье. Другой вариант, «Ресурс», означал, что изображения должны находиться в папке assets, так что это было легко перетаскивать. Даже не пришлось менять относительные пути в заголовке статей.

Первым делом я переместил свои изображения в папку assets вместо static. Я изменил свои изображения на живые с /static/img на /assets/img. Это означало, что мои источники изображений в статьях вообще перестали работать. Активы не создаются во время сборки, если они не обрабатываются. И даже тогда их имя файла динамически генерируется при каждой сборке. Поэтому мне пришлось изменить все вхождения изображений в статьях и шаблонах, чтобы вместо этого использовать ресурс.

Чтобы это работало в моих файлах контента, мне пришлось создать шорткод, это способ Hugo иметь сниппеты внутри Markdown. Вот как выглядит мой. Я взяла шорткод адаптивных изображений, о котором писала в блоге Лаура Калбаг, и изменила его, чтобы он соответствовал моему макету. И поскольку у меня есть анимированные GIF-файлы в моей серии DevTricks, я не изменяю их размер, а просто передаю относительную постоянную ссылку тегу изображения. Я также ничего не делаю с внешними изображениями. Тем не менее, я решил, что если все будет хорошо работать с помощью alt-тегов, я заработаю несколько очков Lighthouse.

{{/* get file that matches the filename as specified as src="" in shortcode */}}
{{ $src := resources.GetMatch (.Get "src") }}
{{ if in (.Get "src") "http" }}
<img src="{{$src}}" {{ with .Get "alt" }}alt="{{.}}"{{ else }}alt=""{{ end }}>
{{ else }}
{{ if in (.Get "src") ".gif" }}
<img src="{{$src.RelPermalink}}" {{ with .Get "alt" }}alt="{{.}}"{{ else }}alt=""{{ end }}>
{{ else }}
{{/* set image sizes, these are hardcoded for now */}}
{{ $tinyw := default "500x" }}
{{ $smallw := default "800x" }}
{{ $mediumw := default "1200x" }}
{{/* resize the src image to the given sizes */}}
{{ .Scratch.Set "tiny" ($src.Resize $tinyw) }}
{{ .Scratch.Set "small" ($src.Resize $smallw) }}
{{ .Scratch.Set "medium" ($src.Resize $mediumw) }}
{{/* add the processed images to the scratch */}}
{{ $tiny := .Scratch.Get "tiny" }}
{{ $small := .Scratch.Get "small" }}
{{ $medium := .Scratch.Get "medium" }}
{{ $large := .Scratch.Get "large" }}
{{/* only use images smaller than or equal to the src (original) image size */}}
<img
  {{ with .Get "sizes" }}sizes='{{.}}'
  {{ else }}
  sizes="(min-width: 35em) 720px, 100vw"{{ end }}
  srcset='
  {{ if ge $src.Width "500" }}
    {{ with $tiny.RelPermalink }}{{.}} 500w{{ end }}
  {{ end }}
  {{ if ge $src.Width "800" }}
    {{ with $small.RelPermalink }}, {{.}} 800w{{ end }}
  {{ end }}
  {{ if ge $src.Width "1200" }}
    {{ with $medium.RelPermalink }}, {{.}} 1200w{{ end }}
  {{ end }}'
  {{ if .Get (print $medium) }}
    src="{{ $medium.RelPermalink }}"
  {{ else }}
    src="{{ $src.RelPermalink }}"
  {{ end }}
  {{ with .Get "alt" }}alt="{{.}}"{{ else }}alt=""{{ end }}>
{{ end }}
{{ end }}

Чтобы использовать этот шорткод изображения в моем контенте, мне пришлось изменить способ вызова моих ссылок с синтаксиса уценки по умолчанию на что-то среднее между Hugo и HTML:

{{< img src="img/posts/web/hugo-performance-before.png" alt="Bad Lighthouse Performance" >}}

Вывод шорткода {{< img >}} выглядит примерно так:

<img sizes = "(min-width: 35em) 720px, 100vw" srcset = " /img/posts/web/hugo-performance-before_hu187b84b0088ba519b328cb2126b97350_79974_500x0_resize_lanczos_2.png 500w, /img/posts/web/hugo-performance-before_hu187b84b0088ba519b328cb2126b97350_79974_800x0_resize_lanczos_2.png 800w, /img/posts/web/hugo-performance-before_hu187b84b0088ba519b328cb2126b97350_79974_1200x0_resize_lanczos_2.png 1200w" src = "/img/posts/web/hugo-performance-before.png" alt = "Bad Lighthouse Performance">

Похоже, я могу изменить размер своих изображений внутри содержимого. Так почему бы мне не сделать то же самое в моих макетах? Потому что где-то мелким шрифтом в документации написано, что я не могу использовать шорткоды вне файлов с контентом. Тем не менее, та же функциональность доступна в шаблонах макета через частичные шаблоны. Как оказалось, мне не нужны адаптивные изображения в моем представлении списка, мне просто нужны изображения намного меньшего размера. Поэтому я не стал воссоздавать всю логику шорткода в частичных шаблонах. Вместо этого у меня был менее сложный, более ленивый подход. Я получаю изображение Resource, я изменяю его размер до 360 пикселей с качеством 85%, используя фильтр Box. Все это приводит к уменьшению размеров, быстродействию и ухудшению качества изображений на домашней странице.

{{ if .Params.images }}
{{ $image := index .Params.images 0 }}
{{ $src := resources.Get $image }}
{{ $small := $src.Resize "360x q85 Box" }}
<img class="post-image" alt="{{ .Title }}" src="{{ $small.RelPermalink }}" >
{{ end }}

После

С этими изменениями я был готов снова проверить свою оценку Lighthouse. Вы тоже можете попробовать, мой сайт - alexlakatos.com.

Вы заметите, что мой Largest Contentful Paint снизился примерно на три с половиной секунды. Я бы назвал это победой. Оценка производительности также поднялась до 99, что я бы назвал чертовски хорошим. Тот факт, что мои оценки доступности и SEO подскочили до 100, объясняется тем, что новый шорткод заставил меня переписать все свои теги изображений. Я потратил время на то, чтобы обновить их до атрибута alt, чтобы мне не пришлось повторять их снова.

Теперь, если бы я хотел сделать больше, мне нужно было бы найти способ заставить конвейер обработки изображений Hugo работать с форматами изображений следующего поколения. Но это история для другого раза. А пока не стесняйтесь обратиться в Твиттер и сообщить мне, если вы нашли это полезным. Или, по крайней мере, развлекательно.

Первоначально опубликовано на https://alexlakatos.com 17 июля 2020 г.