Комментарии 57
используете ли вы формат webp или любые другие новые форматы изображений? И как вы это делаете?Да используем. Написали свой API и сервис для перекодировки ( с кешем, с валидацией, с ресайзингом и прочими фишками).
Я все никак статью не могу закончить для Хабра. У меня есть реальные статистические данные, основанные на выборке размером в 2 млн изображений и с разной степенью сжатия.
Для того чтобы в GooglePage Speed получить за изображения хороший бонус, нужно именно webp ему давать. Порядка 10 баллов в среднем дается за это.
(если статья ещё не скоро будет, то буду крайне признателен, если в личку дадите необходимую информацию или же её крупицы)
Вроде для Апача есть модуль "mod_pagespeed" который умеет перекодировать часто запрашиваемые изображение в webp, если клиент поддерживает данный формат
По моему логичней генерировать в статику webp и отдавать его через тег picture, за одно проработать вопрос с разными разрешениями картинок, для разных разрешений экрана.
Правда, вроде, некоторые браузеры всё-равно могут грузить картинку из медиа-выражения, даже если текущий дисплей устройства не попадает под него.
Спасибо за советы.
Часто приходится встречаться с подгрузкой JS с cdn.js. Видимо нужно в bundle собирать такие вещи.
Сейчас проверил, действительно упал с 100/100 до 99/100 для пет-проекта, беда.
По моему мнению эти все пузомерки большой пользы не несут. Главное руководствоваться здравым смыслом и удобством использования. Хотя рекомендации того же PageSpeed почитать смысл есть.
И ещё один совет, который помогает — положите файлы со шрифтами (woff, ttf и тд) рядом с вашим файлом css, который его запрашивает. Раньше у меня была отдельная папка на сервере для шрифтов, но потом я переместил их скорость загрузки шрифтов увеличилась в 2 раза
Чего, блин??
эти файлы (шрифты) рядом с вашим main.css или style.css. Тогда время подгрузки будет от 70 до 90ms.
Можете поделится правилом для nginx? У меня так и не вышло насьроить (
habr.com/ru/post/237991
<picture>
<source srcset="images/400.webp" type="image/webp">
<img src="images/400.jpg"
width="400" height="300"
>
</picture>
Вы как-то по другому это делаете?
http://webputil.com:8080/api/v1/service/webp/create
данные передаются в заголовках запроса (по ряду причин так было удобнее для этого примера)
X-IMAGE-TOKEN: "85bc92d82651affe7c905d1634751b87" - через пару дней станет невалидным
X-IMAGE-SOURCE: ссылка на jpg ресурс, должна иметь расширение .jpg или .jpeg, get параметры игнорируются
X-IMAGE-WIDTH: желаемая ширина
X-IMAGE-HEIGHT: желаемая высота (можно передать 0 если будем только по ширине ресайзить)
X-IMAGE-QUALITY: от 0 до 100, целое число
X-IMAGE-CACHE-EXPIRY: 1s(econd), 1m(inute), 1h(our), 1d(ay) - время кеширования результата
в ответе помимо тела ответа, есть два заголовка
X-IMAGE-CACHE: HIT
X-IMAGE-URL: ссылка на закешированный результат
За последствия «хабраэффекта» снимаю с себя всякую ответственность :), там небольшая одноядерная vps
1) Определить какие именно картинки двигают контент по мере подгрузки и дать их родителям фиксированную ширину. Этим вы полностью избавите от этих скачков.
Плюсы — скорость решения, гарантия избавления себя от этой проблемы.
Минусы — адаптив, ведь придётся убирать фиксированные размеры. И это может быть не очень грамотно, но мы сейчас ведё речь об оптимизации, а не красоте вёрстки.
2) Изначально делать дизайн и вёрстку так, что бы картинки не были главными в определении размера блока. Пусть либо текст, либо какой-нибудь другой контент будет больше картинки в блоке.
3) Использование sprite. Там ведь изначально есть заданная ширина и высота, потому что там не картинка как img, а background.
По поводу шрифтов, попробуйте еще
<link rel="preload" href="путь до файла" as="font" type="font/woff2" crossorigin="anonymous" />
Но чистый svg не всегда подходит, а именно для иконок. С этим БЭМ ничего нельзя нормально инлайново подключать
– кеширование (настройки nginx для всех типов шрифтов, скриптов, картинок и других типов файлов)
– gzip сжатие
– перенос скриптов в footer (конечно минификация и возможно канкатинация, но тут надо смотреть, как вот автор советует — основное отображение в один файл и портянки в другой)
– скрипты карт вешать на действия пользователей или с максимально допустимой отложенностью
var script = document.createElement('script'); script.type = 'text/javascript'; script.src = 'https://api-maps.yandex.ru/2.1/?lang=ru_RU'; document.body.appendChild(script);
лучше чем async, а timeout на определенное время вообщем может убрать учет скрипта из google анализа
– svg вместо спрайтов (визуально точно лучше)
2) Карты да, тут можно либо подключать её по кнопке, например, вообще делать отдельной страницей (на сам Яндекс или Google).
3) Sprite я использую не только для иконок, а даже для картинок размером до 200кб. Когда их много в одной секции и на них нету никакого функционала (например в секции положительных сторон компании, где обычный текст, и картинка для красоты, но она 400px d ширину). В результате мы убрали лишние запросы на сервер, и одна большая картинка будет меньше весить, чем те по отдельности.
Важно сначала сказать зачем все это нужно.
Согласно официальным заявлениям от Google, метрики производительности проекта используются как один из факторов ранжирования в органическом поиске.
Конечно там не считают миллисекунды. Но обращают внимание на разницу в порядках.
И поскольку, используются цифры именно LightHouse, то борьба за попугаев именно в этой пузомерке имеет практическое значение.
Второй важный влияющий фактор — косвенный. Чем быстрее Ваш проект, тем посетителю приятнее им пользоваться. А значит вероятность того что он вернется Выше.
Реплика
async для подключаемых скриптов (кроме jQuery)говорит как раз о том, что автор до конца не понимает как это работает.
Если Ваши скрипты висят в footer то атрибут async ничем Вам уже не поможет.
И ещё один совет, который помогает — положите файлы со шрифтами (woff, ttf и тд) рядом с вашим файлом css, который его запрашивает.
Это ничему не помогает.
Если у Вас вышло по другому, то тут проблема совсем не в области оптимизации, а в плоскости неадекватности работы Вашей системы. Может что-то с кешированием, может что-то с диском что привело к задержке, может с дефрагментацией.
И не забудьте подключить lazyload.min.js
который из пары десятков? и почему нужно брать именно этот? А как это повлияет на индексирование этих изображений?
О webp.
Уже очень давно для всех типичных популярных серверов есть конфигурации, когда в случае если браузер передает заголовок о поддержке webp, то именно это формат ему и отдается. И так делать нужно.
Конечно, очень хотелось бы все делать «по уму», и размечать изображения через picture с разными source, а не морочить себе голову с конфигурацией веб сервера. Но если Вы, действительно занимаетесь оптимизацией, то боритесь в том числе и за сложность DOM дерева. А лишний source это лишний узел.
Аналогично, совет с инлайном SVG. Однозначно рекомендовать встраивать SVG инлайн может только человек, который не понимает, что такой трюк, помимо того что сокращает количество запросов еще и раздувает дом дерево. И делать такое нужно лишь в случае, если есть необходимо манипулировать таким svg, или издержки на дополнительный запрос, перекрывают издержки на дополнительную память инлайнового svg.
Во всех прочих случаях нужно взвешивать все за и против — есть запас по узлам, можно и инлайн, нет — только внешний src.
Вы спросите почему я так топлю за эти баллы, так это просто требование руководства))
вот только без перехода на личности. просто мнения и аргументы
что б было что выбирать, а не методом научного тыка.
(сомнения в GooglePage Speed есть давно, но только на уровне интуиции… )
Читая мой ответ всё время держите в голове, что я делал оптимизацию ИСКЛЮЧИТЕЛЬНО для GP Speed (дальше GPS).
И внизу ещё есть комментарий, на который я дал развёрнутый ответ, может там будет что-то для Вас тоже интересно.
В первую очередь приведу пример двух сайтов. В первом ничего из моих советов не применено, во втором все пункты выполнены. drive.google.com/open?id=1EcFVkhNQki8J2ZGwKxPyMu-U_3TfJdVS; drive.google.com/open?id=1iUctTHwwbw80vK6Z-stKVvVJDpFrwFnL
1) async — он необходим для того, что бы отработать замечание из GPS которое звучит так: «Сократите время выполнения кода JavaScript», а так же «Минимизируйте работу в основном потоке».
2) Шрифты будут хоть на незначительное время, но быстрее загружаться. Как и говорил, вместе 180ms у меня сейчас 70-90ms.
3) В DOM структуре сайта остаётся и тег img и alt описание, и title. Вы просто не подгружаете её пока не видите. Робот поисковика всё-равно её увидит. (я не разработчик поисковиков, но думаю что это так). Потому что я в google картинка и Яндекса есть наши картинки, если сузить поиск, хотя бы прописав её alt или ссылку на сайт.
Почему именно этот, потому что он проверенный мною и у меня ни разу не было с ним проблем.
4) По поводу webp, нам пришлось отключить pagespeed на нашем сервере, не смотря на то, что он все картинки преобразовывал в webp из-за того, что по сухим цифрам на GPS скорость при включенном pagespeed на 10 баллов меньше. И так было со всеми сайтами. От 10 до 5 баллов плюс после отключения.
5) Опять-таки, увеличение структуры DOM из-за 50 лишних узлов плохо не повлияет на скорость загрузки страницы и на оценку в GPS. А вот 5 лишних svg иконок могут попасть в раздел «Оптимизация, и там будут просить их отложить, скрыть, использовать формат нужны и тд. Как только я начал на сайте все svg переводить в код, то ни разу больше не было рекомендаций от GPS по этому поводу.
1. Обязательным будет свойство async для подключаемых скриптов (кроме jQuery). Это точно избавит вас от замечания в GPSpeed по поводу асинхронной загрузки скриптов.
1.1. Данная рекомендация не обязательна, используйте на свой страх и риск, устанавливая флаги с async вы должны точно знать логику работы js на данной странице.
1.2. Если у вас есть инлайн скрипты которые используют что-то из js файла с async флагом все сломается т.к. на время чтения DOM данный файл не загружен/прочитан, это же касается и js файлов которые грузятся без async флага.
1.3. Все js файлы c async флагом грузятся в том же порядке в котором были спарсены в html.
1.4. Все js файлы которые были вставлены как инекция в html(то как вставляют счетчики гугл аналитикс, например) будут загружены в том же порядке что и объявлены в html(они асинхронны по умолчанию).
1.5. В старых браузерах defer используется как фалбэк для async. Defer “отодвигает” событие DOMContentLoaded пока все файлы с данным флагом не будут прочитаны.
1.6. Уже стандарт хранить ресурсы js/css в футере.
2. Совет банальный, но он очень толковый — старайтесь использовать сложные и массивные библиотеки по минимуму.
2.1. Если все же вынуждены и данные скрипты используются на большинстве страниц, положите их все в отдельный файл даже если в итоге он будет 100кб. Файл кэшируется что в долгосрочной перспективе(путешествие пользователя по сайту) выгодно.
2.2. Старайтесь не использовать jquery библиотеки если есть аналогичные на чистом js.
2.3. Важно: Основная проблема «сложных и массивных библиотек» это цена парса/компиляции кода, 1кб js не равен 1кб картинки (в плане скорости загрузки/интерактивности сайта). Прежде чем ваш js код выполнится браузер делает очень много работы на ним и чем раньше он это закончит тем быстрее приложение станет интерактивно (главный поток станет idle). Поэтому 100кб jquery в разы медленней чем 100кб чистого js который в свою очередь в разы медленней чем обработка 100кб картинки.
3. Свои настройки js библиотек (slick, fancybox) или небольшие фрагменты кода, которые выполняют разные задачи лучше заливать на сервер одним файлом. В моём случае, и скрипт для отправки почты, и маска для input и анимация и всё-всё находится в одном файле build.js ( которому я так же задаю async.
3.1. Страница должна грузить только тот js который необходим на данной странице, ничего лишнего (логика которая используется на другой странице, не нужна).
3.2. Практически идеальный вариант для боевых условий это AMD подход и CommonJS в частности (если говорим о front-end).
4. Этот совет ситуативный, то есть под ситуацию смотрите. Если у вас сразу после открытия страницы на её первом экране выполняется какой-то скрипт, то его будет правильнее подключить отдельно и не давать ему async
Простите, не понял о чем вы, что за скрипт на первом экране?
CSS
1. Тут немного посложнее. К тегу link вам необходимо будет добавить такое свойство
<link media="none" onload="if(media!="all") media="all"" rel="stylesheet" type="text/css", href= main.css>
Именно в таком виде ваши css файлы будут подключаться лишь после дерева DOM. Грубо говоря, это тот же async только для .css
Не советую так делать (это даже не костыль, а подпорка какая-то).
1.1. После каждого обновление CSSOM будет происходит отрисовка страницы, в данном случае страница ПОЛНОСТЬЮ отрисуется еще раз после того как media сменится.
1.2. Если у вас больше 1го css на странице вы не сможете сделать нормальную стратегию загрузки.
1.3. Сам гугл рекомендует LoadCSS.js (https://github.com/filamentgroup/loadCSS)
1.4. На самом деле стили загрузятся последними (onload событие) а не «после древа DOM» (DOMContentLoaded событие)
2. Очень важный и действенный совет! Он добавляет от 5 до 10 баллов гарантированно. Нужно разделить ваш main.css на два файла. В первом будут только те стили, которые подгружаются для того контента, который виден сразу после открытия страницы. Это top bar, header, первая картинка, первая form и тд. В общем то, что вы поместили на «лицо» вашего сайта. Во втором уже всё остальное.
Не совсем понял о чем тут речь, если речь о критическом css то стоит обратить внимание на следующее:
2.1. Если пользователь нажал обновить страницу находясь в нижней части сайта (если длина сайта 4 экрана, например) браузер может восстановить позицию скролла на 3ем экране на котором все будет развалено т.к. критический css уже применен и страница отрисована но еще не применены стили для всей страницы (браузер всегда старается как можно раньше хоть что-то отрисовать).
2.2. Такой метод подходит очень, очень узкому типу сайтов, по моему опыту только лэндингам, сайтам визиткам и всем сайтам которые по PWA патерну сделаны.
Шрифты
Я обнаружил новое для себя css свойство для шрифтов
font-display
А конкретно, его параметр swap, который не дожидаясь подгрузки вашего красивого и тяжёлого шрифта показывает текст в браузере используя встроенный в этот же браузер шрифт (например sans-serif). Это сразу же убирает одну из ошибок в GPSpeed.
1. font-display canIuse 25% global. На нее полагаться нельзя.
2. Сайт который 2 раза рендерит шрифт? Это звучит как антисовет.
3. Sans-serif это не шрифт, это тип гарнитуры, фактически это значит «гарнитура без засечек». Но какой шрифт именно там будет вы не знаете, что скорей всего приведет к сильному «дерганью» при рендере страницы.
4. Если вы используете веб-шрифт как основной значит вы смирились, не стоит больше ничего делать, woff2 и кэша вполне достаточно.
5. Рекомендую dns-prefetch и prefetch в частности. Подробнее можно почитать Robin Rendle (https://css-tricks.com/prefetching-preloading-prebrowsing/).
Подключение шрифтов
1. В основном встречаются два вида подключения — с помощью ссылки (например на google fonts, или же локально, на сервере. Так вот, по поводу второго способа, его так же можно поделить на 2: отдельным css файлом (с помощью link подключаем fonts.css) и напрямую через код (через ваш style.css).
И поскольку сейчас мы ведём речь именно об оптимизации сайта для GPSpeed, то я убедился в том, что лучше подключаться шрифты через ваш главный файл css.
1.1. Тут можно быть и более настойчивым. Шрифты ВСЕГДА должны грузится с того же сервера с которого и css. Путь должен быть относительный без абсолютных ссылок.
2. И ещё один совет, который помогает — положите файлы со шрифтами (woff, ttf и тд) рядом с вашим файлом css, который его запрашивает. Раньше у меня была отдельная папка на сервере для шрифтов, но потом я переместил их скорость загрузки шрифтов увеличилась в 2 раза. (по данным GPSpeed на подключение шрифта Muller раньше у меня уходило 180ms, сейчас 70-90ms)
Вы уверены?
Изображения, картинки и т.д.
За следующие 2 совету ручаюсь, помогли не только мне, а всему офису и даже друзьям отдалённо работающим.
1. Загружайте абсолютно все картинки с помощью lazyloading. Выглядеть это будет так
И не забудьте подключить lazyload.min.js
Лично я рекомендую lazysizes.js
2. Если у вас на странице много svg элементов, то их лучше добавлять чистым кодом, без лишнего обращения к тегу img. Кроме того, svg необходимо ужимать, например, с помощью этого сайта jakearchibald.github.io/svgomg (не реклама).
2.1. Если у вас на сайте много svg элементов и это иконки — используйте svg inline sprites подход, он наиболее выгоден.
2.2. Если у вас на сайте много svg элементов и это картинки — используйте их как img src, так они хотя бы кэшируются.
Но Вам я немного дополню по пунктам.
1) JS. Я там одним предложением, которое вы не поняли (Простите, не понял о чем вы, что за скрипт на первом экране?) и имел ввиду то, что Вы описали 6-ю пунктами) Просто вы более обширно обозначили что нужно добавлять async на свой риск и учитывать выполнение скрипта в разных время и в разных местах.
А по поводу первого экрана — просто пример клиент хочет пустить зимой снег на СТАРТОВЫЙ экран, прям на header. Так вот этому скрипту можно и не задавать async, как вы и сказали. Но если он захочет его пустить где-нибудь в середине или в конце, то ОБЯЗАТЕЛЬНО нужно ему дать async.
GTM я думаю всё и так знают что работает стабильно и загружается асинх. по этому я не упоминал это.
Во 2-3 пункте js прям хорошие толковые советы, я их даже допишу в статью, если буду делат «часть 2, с Вашего позволения. Но мы с Вами и так понимаем, что это достаточно банальные вещи. Я же это делаю для совсем новичков.
2) CSS
1.1 А с чего вы это взяли? Я и на localhost и на сервере проверил в самхы разных разрешениях весь сайт. Ничего ни разу не подгружалось и не перерисовывалось. Всё согласно УЖЕ ЗАРАНЕЕ подгруженным media запросом становилось на свои места. По этому это замечание не имеет место быть.
1.2 Тут я же не понял. В чём проблема и по очереди загружать. У меня ещё не встречалось такого, что бы целый файл css не нужен был с самого начала. Это что же за элемент или случай такой, ради которого нужен отдельный css, который нужно подгружать позже… в общем не понятно. Страница загрузилась и весь css загрузился по очереди, точка.
1.3 LoadCSS.js протестирую. Пока не работал с этим.
2.1-2.2 Совершенно верно. Я показывал это руководству, это не проблема. У нас лендинги, по этому перезагрузка страницы у нас вообще не производится. Разве что пользователь сам её сделает. И всё скачен, но благо это длится 1-4 секунды. Не красиво, но таково требование. По этому сначала стартовый экран, а потом уже main.css. И да, мне нужно было об этом упомянуть в статье, о скачках.
ШРИФТЫ
1-4 font-display ну и что, что он 25%. Прописать то всё-равно нужно и дальше продолжать оптимизировать этот аспект. Пусть себе висит в @ font
-face и помогает где может, он ничего не нарушит. И пока грузится страница используется ВСТРОЕННЫЙ в браузер шрифт и ничего второго не рендерится. Он ообще не на сервере находится, нечему рендерится. И даже если там что-то при каждом открытии любого сайта рендерится (arial, robots, sans-serif и тд), то это даже не заметно, там милисекунда и готово. тут дело вкуса — во время подгрузки шрифта пустое место или отображение текста хоть как-то. И напомню, что это отдельное замечание в GPSpeed, для которого эта статья и предназначалась.
5 Это тоже протестирую.
Подключение шрифтов. 2 Вы быстрее пробежите 40 метров или 200? А зачем тогда заставлять main.css бегать в лишнюю папку, и там искать файлы? Пусть они сразу будут вплотную друг к другу. И да, по цифрам я уверен, лично проверил. Хоть это и милисекунды, но так ведь и добивается оптимизация, по крупицам.
ИЗОБРАЖЕНИЯ
1 — 2.1 lazysizes.js — не работал с этим, протестирую.
Вы быстрее пробежите 40 метров или 200? А зачем тогда заставлять main.css бегать в лишнюю папку, и там искать файлы? Пусть они сразу будут вплотную друг к другу.
Файл main.css никуда не бегает, плотность файлов в файловой системе на скорость доступа и отдачи контента не влияет. Вам выше ответили, что данный эффект связан с неправильными настройками среды веб-сервера (или методикой измерений).
Было бы здорово, если бы вы написали как оптимизировать под 100 по PageSpeed обычный сайт на Worpdress, где стоят обычные плагины. Это мне кажется более полезная информация будет.
За размещение шрифтов в отдльной папке даже незнал что + даст)
Добавит только можно
если есть подгрузка из других доменов
Шрифты я загружаю первым формат woff2 и вторым woff остальные уже пару лет как неактуальны
Так же есть сервис для генерации собственного иконочного шифта (не реклама icomoon.io)
Ну и очень важная часть это чтоб сервер отдавал максимально быстро контент.
Стост использовать Cloudflare если если проект позволяет Netlify либо другой аналог который дат cdn, HTTP2
Так же сейчас для pagespeed влияет анализ программой Lighthouse
https://developers.google.com/web/tools/lighthouse/
Но чтоб на ней везде по 100 балов получить надо pwa делать или service worker настроить на кэширование, на моем проекте только этого нехватает, может как доделаю напишу статью об этом))
Спасибо за статью:)
И ещё один совет, который помогает — положите файлы со шрифтами (woff, ttf и тд) рядом с вашим файлом css, который его запрашивает. Раньше у меня была отдельная папка на сервере для шрифтов, но потом я переместил их скорость загрузки шрифтов увеличилась в 2 раза. (по данным GPSpeed на подключение шрифта Muller раньше у меня уходило 180ms, сейчас 70-90ms)
Готов спорить, что у вас на бэкенде стоит Apache с включенным «AllowOverride All», суть которого в сканировании всех директорий в пути запрошенного URL на наличие .htaccess и каждый дополнительный слэш в пути, как уже писали в комментах: «Все знают что каждый слэш в адресе добавляет 50-70мс!» делает вот именно это ))) А это — не совсем правильно настроенный вэб-сервер, т.к. от этого не спасает ни дисковый кэш, ни SSD (хотя будет в разы быстрее) или какой memcache — оно всё равно на каждый запрос будет топать в директорию, искать файл .htaccess и если такой есть будет его парсить…
Оптимизация сайта для GooglePage Speed (учтены все особенности после его обновления) Часть 1