Оптимизация сайта для Google page speed и Lighthouse

Оптимизация сайта для Google page speed и Lighthouse HTML, CSS

В этой статье я описал множество способов и приемов которыми можно оптимизировать скорость загрузки и отрисовки страницы. С помощью них вы сможете добиться высоких показателей в Google Page Speed Insights, Lighthouse и других тестах.

Валидация HTML и CSS

Перед тем как оптимизировать скорость загрузки и отрисовки страницы необходимо убедиться что в коде страницы нет ошибок. Для проверки используем сервисы для валидации HTML и валидации CSS кода.

Валидатор HTML: https://validator.w3.org/
Валидатор CSS: https://jigsaw.w3.org/css-validator/

Веб-шрифты формата woff2. Отказ от Google Fonts

Для оптимизации скорости загрузки лучше разместить веб-шрифты в проекте. На сегодняшний день можно смело использовать формат woff2 – он современный, оптимизированный по весу, поддерживается всеми браузерами, кроме IE и Opera mini. Сам сервис Google Fonts использует только его, отказавшись от всех остальных форматов.

Скачать шрифт в формате ttf для конвертации в woff2 можно на том же Google Fonts. Сервисы для конвертации в woff2: transfonter.org или fontsquirrel.com

При конвертации, или при описании директивы @font-face не забудьте указать в ней CSS свойство font-display: swap; это позволит не задерживать отображение текста, пока загружается веб-шрифт.

К тому же при использовании Google Fonts браузер делает запросы на два разных сервера. CSS файл с описанием шрифта находится на одном домене, а сами шрифты на другом.

Предварительная загрузка шрифтов и других ресурсов

Одной из рекомендация от Lighthouse является предварительная загрузка ресурсов которые могут понадобиться на странице.

Так можно указать предварительную загрузку шрифтов которые используются на всем сайте или только в области первого экрана. Можно указать предварительную загрузку фонового изображения для шапки сайта. Тут все зависит от конкретного сайта.

Делается это тегом link внутри тега head. Пример предварительной загрузки шрифтов:

<link rel="preload" href="./fonts/montserrat/Montserrat-Bold.woff2" as="font" crossorigin="anonymous">
<link rel="preload" href="./fonts/montserrat/Montserrat-ExtraBold.woff2" as="font" crossorigin="anonymous">
<link rel="preload" href="./fonts/montserrat/Montserrat-Medium.woff2" as="font" crossorigin="anonymous">

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

Сжатие jpg и png графики

После экспорта jpg и png графики из макета, она зачастую весит больше, чем могла бы. Это зависит от алгоритмов и степени сжатия. Для оптимизации веса рекомендую использовать специальные сервисы.

Сервис tinypng позволяет значительно сократить вес jpg и png файлов. Порой получается сэкономить до 90% от исходного веса файла.

Сжатие jpg и png графики: https://tinypng.com/

Сжатие svg графики

SVG — это векторный формат, который полностью описан через код и формулы. Но несмотря на это и его можно сжать, значительно сократив количество кода и выиграв в весе изображений. Сжатие SVG зачастую не дадут под сотни сэкономленных килобайт, как это может быть с jpg форматом, однако иногда это может быть полезно и позволит сократить вес svg файла на 20-30%.

Сжатие svg графики: https://vecta.io/nano

Использование webp и других современных форматов графики

webp может составить хорошую конкуренцию png и jpeg (зависит от метода сжатия jpeg) форматам, без особой потери качества. Если на вашем сайте много оформительской png графики, то можно рассмотреть её конвертацию в webp.

У webp есть один минус — он не поддерживается в Safari, поэтому нужно будет помещать его в тег picture и делать fallback до jpeg формата. На nginx серверах есть возможность настроить автоматическую отдачу webp формата тем браузерам которые его поддерживают, чтобы настроить это — обратитесь к вашему системному администратору.

Для ручной подготовки webp графики, можно воспользоваться сервисом squoosh.app чтобы оптимизировать графику не только в webp но и в более компактный, по сравнению с обычным, jpeg формат (например используя метод сжатия MozJPEG).

inline код для svg графики

Вставив svg графику через inline код в html разметку страницы, мы уменьшаем количество запросов к файлам. Меньше подключений файлов, означает меньше запросов, это напрямую влияет на скорость загрузки страницы. Делать inline вставку svg графики стоит аккуратно. Если подразумевается что эта графика будет редактироваться через CMS, то от inline способа стоит отказаться. Если это верстка элемента интерфейса, который не является изменяемым контентом через CMS — то inline способ будет подходящим решением.

Удаление лишнего CSS кода

Стоит позаботиться о том чтобы в CSS файле не было селекторов с стилями которые не используются в проекте. Тут нужно либо внимательно писать стили, не создавая селекторы которые не используются, либо проверять себя через сервисы которые помогут найти неиспользуемый CSS в проекте. Также посмотреть неиспользуемый CSS можно через DevTools в Chrome браузере. Используя Gulp сборку можно воспользоваться gulp-плагинами, которые налету будут удалять ненужный CSS код и он не будет попадать в итоговый CSS файл.

Сервисы по поиску неиспользуемого CSS:

Плагин для Gulp и не только: purge.css

Отключение sourcemaps в CSS и JS

Исходные карты полезный инструмент во время разработки. С помощью них мы понимаем где изначально описан тот или иной селектор или JS код. Но файлы sourcemaps порой весят больше чем сам CSS файл, поэтому при оптимизации скорости загрузки — от них стоит отказаться. Они нужны только при разработке и отладке, но не на продакшене.

Сжатие (минификация) CSS, JS, HTML кода

На CSS файлах можно сэкономить несколько десятков КБ, это конечно зависит от размеров проекта. Для этого в CSS стоит минифицировать. Это такое сжатие CSS кода, когда из него удаляются все символы которые можно удалить, при этом оставив файл работоспособным. К ним относятся пробелы, переносы строки, точки с запятой после последнего свойства в селекторе. Визуально такой файт становится нечитаемым, зато за счёт такой чистки — его вес может уменьшится на 30%

Также подобное сжатие можно проводить для HTML и JS кода. Такая операция позволит сократить вес проекта на несколько десятков килобайт.

Объединение CSS, JS файлов

Если стили для проекта написаны в нескольких файлах и подгружаются отдельными тегами link, то имеет смысл объединить их в единый файл. Тоже самое стоит сделать и с JS скриптами. Таким образом мы уменьшим количество запросов на сервер.

Вынесение критической части CSS кода в inline

Если CSS файл имеет вес более 100Кб то можно вынести из него стили которые нужны для загрузки первого экрана страницы — который видит пользователь. Эти стили минифицуируются и размещаются inline кодом через тег style внутри тега head.

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

Здесь преследуется цель — отрисовать первый экран сайта как можно быстрее, счет идет на миллисекунды.

Отложенная загрузка для изображений

Если на сайте большое количество изображений, то имеет смысл установить скрипт lazy load загрузки. С таким скриптом изображения будут загружаться только в тот момент когда попадают в область видимости в браузере, и не будут блокировать загрузку всего сайта, загружаясь когда они еще не нужны.

Отложенная загрузка для iframe

Карты Yandex и Google Maps, iframe блоки для видео с Youtube и другого контента. Если они не нужны мгновенно при открытии сайта, то стоит сделать для них отложенную загрузку.

Разделение на модули и отложенный запуск JavaScript кода

Если на проекте есть много JS кода, то возможно эффективным будет разделение кода на отдельные файлы, и отложенный запуск.

Например в проекте используется библиотека карусели, которая работает на библиотеке jQuery. Также на сайте есть скрипты для открытия навигационного меню и прочие небольшие интерактивные вещи написанные отдельными скриптами на нативном JS.

В нашем примере скрипты на чистом JS присутствуют уже в шапке сайта и на первом экране. А карусель которая требует jQuery находится в самом низу сайта, и чтобы до неё добраться нужно скроллить несколько экранов.

В таком случае, можно изначально загрузить только файл с нативными JS скриптами. А после по скроллу, при приближении к слайдеру — начать загружать библиотеку jQuery, библиотеку карусели и его инициализацию на странице. Для этого можно написать специальные JS функции.

Также может пригодиться setTimeout для отложенного запуска скриптов, чтобы они запускались спустя определенное время, это может быть от 100 до 300 миллисекунд, не блокируя и не замедляя отрисовку первого экрана сайта.

Включить кэширование ресурсов на стороне клиента

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

Для хостингов с использованием сервера Apache сделать это можно настройкой в файле .htaccess. Для оптимизации под Google Page Speed 1-го месяца кэширования порой недостаточно. Поэтому предлагаю ниже вариант файла .htaccess c установкой срока кэширования в 1 год.

Пример .htaccess файла с настройками для кэширования:

<ifModule mod_expires.c>

# Add correct content-type for fonts & SVG
AddType application/font-woff2 .woff2
AddType image/svg+xml .svg

ExpiresActive On
ExpiresDefault "access plus 12 month"

# Cache Images
ExpiresByType image/x-icon "access plus 12 month"
ExpiresByType image/jpeg "access plus 12 month"
ExpiresByType image/png "access plus 12 month"
ExpiresByType image/gif "access plus 12 month"
ExpiresByType image/svg+xml "access plus 12 month"

# Cache Fonts
ExpiresByType application/font-woff2 "access plus 12 month"
ExpiresByType image/svg+xml "access plus 12 month"

# Cache other content types (CSS, JS, HTML, XML)
ExpiresByType text/css "access plus 12 month"
ExpiresByType text/javascript "access plus 12 month"
ExpiresByType application/javascript "access plus 12 month"
ExpiresByType application/x-javascript "access plus 12 month"
ExpiresByType text/html "access plus 12 month"
ExpiresByType application/xhtml+xml "access plus 12 month"

</ifModule>

<ifModule mod_deflate.c>

AddOutputFilterByType DEFLATE text/html text/plain text/xml application/xml application/xhtml+xml text/css text/javascript application/javascript application/x-javascript application/font-woff2 image/svg+xml

</ifModule>

Статья по теме про настройку сайта через .htaccess, в том числе и про кэширование: https://habr.com/ru/post/154643/

gZip или другой способ сжатия данных сайта

Рекомендуется включить на сервере сжатие данных перед их отправкой клиенту. Так можно уменьшить размер текстовых ресурсов, следовательно ускорить загрузку сайта.

Проверить включено ли на вашем сайт gZip сжатие можно на сервисе: gidnetwork.com/tools/

Если вы хотите узнать применяется ли вообще какая либо технология сжатия, то можно проверить сайт на сервисе: whatsmyip.org/http-compression-test/

Если сжатие выключено, и нет возможности включить его настройками на хостинге, то можно сделать это внеся инструкции в .htaccess

Пример .htaccess файла с настройками для gZip сжатия:

<IfModule mod_deflate.c>
# Compress HTML, CSS, JavaScript, Text, XML and fonts
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml

# Remove browser bugs (only needed for really old browsers)
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
Header append Vary User-Agent
</IfModule>

Включить протокол HTTP/2

Для наших задач протокол HTTP/2 хорош тем что позволяет сразу передавать несколько файлов от сервера к клиенту, избегая длинных очередей. С HTTP/1 это было невозможным. Включив HTTP/2 вы сразу значительно ускорите загрузку сайта.

SSL сертификат

SSL сертификат необходим для сайта чтобы включить HTTP/2 протокол. Можно приобрести платный либо воспользоваться бесплатным Lets Encrypt SSL сертификатом.

Сервисы бесплатных SSL сертификатов:

Accessibility — доступность

Доступность это не про скорость, но это про прохождения тестов на PageSpedd и Lighthouse. По доступности хочу дать несколько рекомендаций, который помогут вам изначально делать правильную верстку.

Размеры для изображений

При отрисовке страницы браузеру важно понимать размеры изображения, чтобы зарезервировать под него место.

Если этого не производить то происходит смещение контента, когда при открытии сайта мы видим как контент «прыгает» по странице, обычно смещаясь вниз, после подгрузки изображений, которые идет перед ним.

Чтобы такого не происходило стоит указать ширину изображений в тегах img через атрибуты width и height. Тогда браузер будет заранее резервировать место под них, и смещение контента не произойдет.

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

Атрибут aria-label для тегов button

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

Пример использования атрибута aria-label:

<button aria-label="Navigation" id="openNav" >
	Open navigation
</button>

Теги label c описанием элементов формы

Для скрин-ридеров необходимо добавлять теги label c описанием для каждого элемента формы. Даже если такой тег отсутствует по дизайну, его стоит разместить и скрыть через CSS.

Пример html:

<label for="searchInput" class="visually-hidden">Поиск на сайте</label>
<input type="text" class="search__input" placeholder="Введите текст для поиска" id="searchInput">

Стили для скрытия тег label:

.visually-hidden {
	width: 1px;
	height: 1px;
	position: absolute;
	left: -6000px;
}

Заключение

При оптимизации сайта под Google Page Speed и Lighthouse — стоит понимать что главным приоритетом должно оставаться удобство пользования сайтом и скорость его работы, а не нарисованные синтетические баллы.

Некоторые приемы оптимизации могут быть неудобны с точки зрения разработки при частом обновлении проекта.

Не все перечисленные методы являются необходимыми для применения для выхода в зеленую зону оценки. Порой достичь зелёной зоны можно внедрив лишь часть рекомендаций.

В этой статье рассмотрены только аспекты HTML верстки. Если проект работает на CMS или фреймворке, то также стоит оптимизировать работу сервера и бэкенда.