Как сделать адаптивную загрузку изображений из Netlify Large Media. Что такое ленивая загрузка? И как все это использовать в HTML и Markdown. Что будет работать, а что нет.

Это третья статья об оптимизации изображений, которую я реализовал в своем блоге на Nuxt с помощью Netlify CMS.

Проверьте предыдущие, если вы еще не сделали этого:

  1. Сервис оптимизации изображений для Netlify CMS и Nuxt - о том, как я решил использовать для этого Netlify Large Media.
  2. Исправление установки Netlify Large Media - о моем ужасающем опыте настройки Netlify Large Media.

В этой статье я расскажу о том, как я реализовал все это на своем веб-сайте. Что сработало, а что нет.

Изображения в HTML

Начнем с изображений, созданных с помощью HTML.

Вот как это делается со мной:

<img
  src="/img/sample_image.png?nf_resize=fit&w=250"
  loading="lazy"
  alt=". . ."
/>

Загрузка оптимизированных изображений из Netlify Large Media

Я добавляю ?nf_resize&w=250, чтобы загрузить изображение с шириной, уменьшенной до 250 пикселей, и пропорциональной высотой.

Почему я выбрал 250px? Я проверил, какова максимальная ширина конкретного изображения при рендеринге, и соответственно установил ширину.

На моем сайте изображения обычно показываются в разных размерах. Для настольных браузеров это фиксированная ширина. На мобильных устройствах он привязан к ширине экрана, поэтому может варьироваться от 30px до 236px (что-то вроде этого), поэтому я просто выбрал 250px, поскольку он никогда не становится больше этого.

Дополнительные параметры, которые можно указать при запросе изображения из Netlify Large Media, вы можете найти в документации.

Ленивая загрузка

Добавление loading="lazy" говорит о том, что браузер должен загружать изображение только тогда, когда оно находится рядом с видимым окном просмотра.

Когда я не устанавливал это в начале, страница загружалась следующим образом: при открытии страницы браузер рисует первый HTML-код и начинает загрузку всех изображений, используемых на текущей странице, и пока он не завершится, страница будет отображаться как загружаемая. Если на странице много изображений, на это потребуется время. Иногда много.

При установке loading="lazy" браузер загружает только те изображения, которые находятся в видимой части страницы и в области 1250px- 2500px вниз по ней (doc). По крайней мере, в браузерах Chromium это должно работать именно так.

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

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

Пробуем srcset и sizes

Я также пробовал сделать адаптивную загрузку изображений с помощью следующего кода от Mozilla:

<img srcset="path_to_image.png?nf_resize=fit&w=180 180w,
             path_to_image.png?nf_resize=fit&w=250 250w"
     sizes="(max-width: 400px) 180px, 250px" 
     src="path_to_image.png?nf_resize=fit&w=250" 
     alt=". . ." 
/>

Исходя из кода, это означает, что на экранах шириной до 400 пикселей браузер должен запрашивать изображение со следующими параметрами: ?nf_resize=fit&w=180 180w. Следовательно с шириной 180 пикселей. На экранах шириной более 400 пикселей он должен загружать изображение со следующими параметрами: ?nf_resize=fit&w=250 250w. Таким образом, ширина должна быть 250 пикселей.

Но это не сработало.

При указании sizes в процентах от vw (область просмотра) все работает, как вы увидите позже с изображениями Markdown. Но с px спецификациями ничего не работало. Изображения всегда загружались с такими параметрами: ?nf_resize=fit&w=250 250w 🤷‍♂️.

Поигравшись с ним некоторое время, я понял, что могу просто оставить его с одним параметром ?nf_resize=fit&w=250 250w. Как и раньше, вот так:

<img
  src="/img/sample_image.png?nf_resize=fit&w=250"
  loading="lazy"
  alt=". . ."
/>

Мои изображения становятся действительно отзывчивыми на мобильных устройствах, и поиск правильных vw для разных макетов является значительной проблемой (по крайней мере, для меня).

Я также скачал изображения, чтобы сравнить их размеры. 250px один - 114 кб, 180px - 63,3 кб. Разница вдвое больше, но после запуска тестов Page Speed ​​с 180px изображением я не заметил никаких улучшений🤷‍♂️.

Загрузка оптимизированных изображений из Markdown

Выполнить всю эту оптимизацию для сообщений в блогах немного сложнее.

Все мои сообщения написаны на Markdown и конвертируются в HTML плагином markdown-it.

Язык Markdown имеет некоторые спецификации и ограничения на способ описания изображений. Вот структура спецификации изображения: ![Alt text people will see if picture can't be seen](https://link.of/image "Title to show under the image"). Не так уж много вещей, которые мы могли бы указать. К счастью, мы можем многое изменить в том, как Markdown переводится в HTML, с помощью дополнительных markdown-it- плагинов.

Ленивые изображения

Прежде всего, я нашел и добавил плагин, который добавляет loading="lazy" к каждому изображению, отображаемому с помощью markdown-it.

Вот он: markdown-it-image-lazy-loading. ! Если вы также планируете загружать оптимизированные изображения, добавляя к изображениям параметры URL, подождите немного, прежде чем добавлять их. Есть способ использовать только плагин, который я покажу далее, без необходимости устанавливать его. Просто переходите к следующему разделу.

После установки loading="lazy" скорость загрузки страниц блога с большим количеством изображений резко возросла. Этот атрибут действительно необходим. Результаты смотрите в следующей статье.

Изображения с srcset и sizes

Затем я попытался добавить пакет markdown-it-responsive, который должен добавлять атрибуты srcset и sizes к каждому изображению, но это вообще не сработало. У меня ошибка рендеринга HTML и битые страницы☹️.

После дополнительного поиска я нашел этот плагин: markdown-it-modify-token. Проверив его, я понял, что он будет отлично работать, и я могу делать с ним все, что мне нужно.

Некоторое время и родился этот код:

modifyToken: function(token, env) {   
   switch (token.type) {     
     case "image":       
         token.attrObj.srcset = 
             `${token.attrObj.src} nf_resize=fit&w=300 300w, ` + 
             `${token.attrObj.src}?nf_resize=fit&w=600 600w`;       
         token.attrObj.src = token.attrObj.src + "?
         nf_resize=fit&w=600";       
         break;   
    } 
},

Указывая srcset таким образом, я говорю браузеру: вот два изображения с шириной 300px и 600px, сами решите, какое изображение загружать в соответствии со 100% шириной области просмотра.

Сначала я также добавил атрибут size следующим образом:

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

Это работает, но поведение немного странное (по крайней мере, для меня). Когда ширина экрана 200px, браузер загружает изображение с 300px шириной, но когда ширина экрана установлена ​​на 250px, загружается изображение с 600px шириной ... Я этого не понимаю😐.

И снова указание sizes в px привело только к загрузке 600px изображения ...

Вот код, который я пробовал:

token.attrObj.sizes = "(max-width: 400px) 300px, 600px"

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

Как я писал ранее, здесь можно отказаться от использования плагина markdown-it-image-lazy-loading для дополнительного кода в

modifyToken: function(token, env) {
}

Просто добавьте это:

token.attrObj.loading = "lazy";

Здесь, в case "image"::

modifyToken: function(token, env) {   
   switch (token.type) {     
     case "image":       
         token.attrObj.srcset = 
             `${token.attrObj.src}?nf_resize=fit&w=300 300w, ` + 
             `${token.attrObj.src}?nf_resize=fit&w=600 600w`;       
         token.attrObj.src = token.attrObj.src + "?
         nf_resize=fit&w=600";
         
         token.attrObj.loading = "lazy";   
         break;   
    } 
},

Кстати, если вы хотите всегда загружать изображения одного размера, просто удалите srcset сеттер. Это выглядело бы так:

switch (token.type) {   
  case "image":     
      token.attrObj.src = token.attrObj.src + "nf_resize=fit&w=600";     
      
      // token.attrObj.loading = "lazy";     
      break; 
}

Как вы помните, лучше иметь первые изображения без отложенной загрузки, но с изображениями из Markdown это немного сложно. Для уценки нужно написать дополнительную логику, и мне не стоит тратить время на это. Да, есть небольшое снижение производительности, как говорят ребята из Google, но я думаю, это не обернется для банка.

Это все, что я сделал для лучшей загрузки изображений на свой сайт. В следующей статье вы можете проверить полученные мной улучшения скорости страницы. Они довольно солидные ».

Чтобы узнать больше о создании моего блога, присоединяйтесь ко мне в Twitter, пока я продолжаю делиться своими достижениями.

Первоначально опубликовано на https://nikitagoncharuk.com 4 сентября 2020 г.