perfScan - Секреты быстрых сайтов
1.37K subscribers
53 photos
56 links
Делюсь секретами как создавать быстрые сайты и ускорять существующие.

По всем вопросам: @fenixru - помогаю ускорять сайты.

При использовании материалов канала обязательно указание авторства.

Поддержать автора: https://pay.cloudtips.ru/p/4ad68fa9
Download Telegram
- Привет. Я - Антон Белогородцев, и я специалист по ускорению сайтов.
- Привет, Антон.

На канале будут технические моменты, которые помогут сделать сайт быстрее, и перестать вообще делать медленные сайты. Будут как посты от меня, так и полезные репосты из других пабликов по фронтенду и разработке.
👍17🔥5👏2💩21
Про Google Fonts

❗️Больше всего на время загрузки сайта влияет число установленных соединений.
Поэтому первое, что мы делаем при оптимизации сайта - избавляемся от google-fonts.

Google-Fonts удобен для разработчиков, подключил один файл стилей, указал шрифт и все готово.

Но тут скрывается даже не одно, а целых два соединения: fonts.googleapis.com, и fonts.gstatic.com. С первого соединения грузится css, а со второго сами файлы шрифтов, это крайне негативно влияет на показатели FCP/LCP, так как при стандартном подключении файлы стилей являются еще и блокирующими. Тоесть пока не будет установлено соединение с fonts.googleapis.com и не будет загружен файл стилей, мы не получим отрисовку.

Хорошо еще, что сейчас используется параметр font-display:swap по умолчанию при подключении, без него блокиовали еще и сами файлы скриптов, и кстати, на многих сайтах до сих пор используется старое подключение.

Подключайте шрифты со своего хоста, уменьшайте число соединений, и ускоряйте свои сайты.
👍9🔥3👏21💩1
Кэширование в Google Fonts

📌 В прошлом посте забыл упомянуть про очень популярное заблуждение по поводу кэширования шрифтов и CSS из Google Fonts. Принято считать, что если пользователь был на любом сайте, который использует те же шрифты подключенные также из Google Fonts, то повторной загрузки этих шрифтов не произойдет.

Это не так. Уже несколько лет для каждого сайта используется своя песочница для кэширования даже сторонних ресурсов, что позволяет избежать проблем безопасности и несанкционированного трекинга. Поэтому загрузка будет производиться для каждого сайта независимо, и отдельного кэша со шрифтами google-fonts использовано не будет.

Значит, как и упоминалось ранее ранее, подключайте шрифты только со своего домена.
👍9🔥2👏2💩1
Как скачать шрифты Google Fonts

📌 Чтобы скачать шрифты с Google Fonts можно использовать бесплатный инструмент: https://gwfh.mranftl.com/fonts

Переходим, выбираем слева шрифт, и далее выбираем Modern Browsers, чтобы не грузить устаревшие версии файлов шрифтов.

Сервис сгенерирует фрагмент CSS для подключения шрифтов, и скачиваете архив. Используйте из архива только woff2 и woff. Более старые форматы в своей работе уже можно не использовать, убедитесь сами в поддержке: https://caniuse.com/woff2 и https://caniuse.com/woff.

Если вы используете систему сборки проекта, то почти для каждой из них есть аналоги, которые скачают и подключат шрифты в ваш проект. Хотите узнать какие - пишите в комментариях.
👍9🔥3👏21
📌 Время ответа сервера настолько большая тема, что я думаю, будет не один десяток постов.
👍5🔥2👏2👎1
Время ответа сервера: Кэширование

Время за которое человек успеет заметить переход - это 150 миллисекунд. Если ответ сервера меньше, то все вообще отлично, если больше, то будет заметен переход, дискомфорт у пользователей возникает уже после 400 миллисекунд. Если ответ сервера больше 400 миллисекунд, то стоит уже работать над улучшением этого показателя. Стоит также помнить, что показатель зависит от нагрузки на сервер, от качества сети сервера и клиента, а также от задач, которые выполняет скрипт перед ответом.

Отсюда и следуют все возможные оптимизации этого показателя: увеличение мощности сервера, снижение нагрузки, оптимизация ресурсоемких операций, которые выполняются во время загрузки страницы, и также подключение кэширующего CDN.

Проще всего "закидать железом": докупить серверу больше ресурсов, использовать кластер, или облако. Однако это в долгосрочной перспективе и самый дорогой способ. По оптимизации самого приложения идеальных советов нет, так как все зависит от того, что делает приложение, насколько важна динамичность блоков и тд.

Используйте кэширование. Для начала включите все возможные методы кэширования в самом приложении или CMS, и уже вторым этапом - используйте полностраничный кэш nginx, это будет работать практически из коробки на любом хостинге. Однако помните, что полностраничный кэш nginx убьет всю динамику, которая есть на странице со стороны backend, все пользователи будут видеть одну страницу. Но даже если вы сделаете раздельное кэширование для разных пользователей, то динамика рандомных блоков и подобный функционал будет потерян.

Приведу в пример самую популярную CMS: Wordpress. Пример хорошей отдачи кэша без потери контроля над ним описан у них в статье на официальном сайте: https://wordpress.org/support/article/nginx/ по ссылке есть примеры сразу для нескольких плагинов кэширования.

Для кэширования динамических блоков можно использовать технологию SSI - Server Side Include, Это когда backend отдает части шаблона, а сборку делает уже nginx, собирая частично из закэшированных кусков, частично из динамических. Это хорошее решение для больших и посещаемых проектов, например сайтов СМИ.

❗️ Всегда ориентируйтесь на само приложение, не используйте универсальные советы из интернета, если не уверены на сто процентов, что они вам подходят.
👍10🔥3👏2👎1
Сжатие изображений на лету

⁉️ Самый частый вопрос, и в то же время, далеко не самый важный - это оптимизация изображений. Многие думают, что это чуть ли не ключевой вопрос, решив который, показатели сразу резко вырастут. Это далеко не так: может улучшиться только если изображение весило 1-2 мегабайта и при этом являлось LCP-элементом. В то же время, ожидать загрузки изображений не хочет никто, даже на медленном интернете.
🔥11👍2👏2💩1
Самый оптимальный, быстрый и удобный способ без лишней разработки сжать все изображения на сайте - делать это на лету при помощи специальной бесплатной open source утилиты: https://github.com/webp-sh/webp_server_go

Проще всего развернуть такую утилиту при помощи Docker, а файл Docker-Compose можно взять в подробной документации: https://docs.webp.sh/usage/docker/

Самое главное - помните, все изображения, особенно LCP-элементы должны находиться на том же хосте, что и ваш сайт, чтобы не пришлось устанавливать еще одно соединение для загрузки. Проксировать в докер можно все файлы по типам, или какую-то конкретную папку, используя секцию location в nginx. При этом поддерживаемые браузеры будет загружать WebP/AVIF, а неподдерживаемые обычный JPG, однако и он будет также предварительно оптимизирован. Быстро и удобно.

⚠️ Обратите внимание, конвертация в AVIF изначально выключена, чтобы не создавать нагрузку. Можно включить в конфиге всего одной опцией.
👍6🔥5👏2💩1
Отладка CLS

⚡️ CLS - это смещение контента во время загрузки и использования страницы. Lighthouse и Google PageSpeed Insites показывают смещения, которые происходят на странице в момент ее загрузки. Однако данные в Core Web Vitals попадают за все время, пока пользователь использует страницу. Не всегда понятно, какой DOM-элемент вызывает смещение других элементов на странице после ее загрузки. Для быстрой отладки таких смещений можно использовать простой скрипт, вставив его в консоль браузера:

let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
👍11🔥5👏2
💬 Увидел недавно на одном сайте вот такой фрагмент кода в JS.
А раз это хоть и опосредовано, но касается Performance, то давайте обсудим.

const prefetchPage = e => {
if (e.target.tagName !== "A") {
return;
}
if (e.target.origin !== location.origin) {
return;
}
const removeUrlFragment = url => url.split("#")[0];
if (removeUrlFragment(window.location.href) === removeUrlFragment(e.target.href)) {
return;
}
let l = document.createElement("link");
l.rel = "prefetch";
l.href = e.target.href;
document.head.appendChild(l);
}
document.documentElement.addEventListener("mouseover", prefetchPage, {
capture: true, passive: true
});
document.documentElement.addEventListener("touchstart", prefetchPage, {
capture: true, passive: true
});


Что вы думаете об этом?
Вы бы стали использовать такое решение?
👍5🤔5🔥2👏2
Отложенная загрузка изображений

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

1. Индексация изображений поисковиками должна проходить быстро и без проблем.
2. Загрузка должна проходить в момент появления элемента на экране, но без больших математических вычислений.
3. Необходима возможность очень гибко управлять этим механизмом.
4. Не должно быть зависимостей от других библиотек.

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

Модули для vue, jquery, react также не подходят, так как требуют сторонней библиотеки, и соответственно загрузка начнется только после парсинга всех бандлов с зависимостями, а это время и ресурсы клиента.

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

Остается хорошее решение на IntersectionObserver API, которое не выполняет никаких вычислений, однако с ним возможна проблема с индексацией. Давайте его и доработаем.

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

Код на Codepen
👍12🔥6👏2
Откладываем Youtube

❗️ При вставке кода Youtube или любого другого плеера, будь то Rutube, VK или Vimeo на свой сайт, мы получаем загрузку самого плеера, кодов отслеживания сервиса, аналитику сервиса, огромные бандлы JavaScript, а в некоторых случаях и часть видео, даже если человек его не запускает.

Например, заходит на страницу 1000 человек в день, а видео запускает только 20, но все "добро" от видеохостинга "прилетает" всем. Давайте посмотрим на примере плеера Youtube, какой размер кода получает пользователь даже не запуская видео:

HTML: 64 килобайта
CSS: 346 килобайт
Изображения: примерно 150 килобайт (в зависимости от видео и его превью)
Шрифты: 17 килобайт
JavaScript: 2.47 мегабайта
XHR-запросы: примерно 100 килобайт

Итого: примерно 3,5 мегабайта
❗️

Но что самое страшное: 10 новых соединений‼️

Мы только подключили одно видео через код YouTube, а пользователь скачал 3,5 мегабайта и установил 10 соединений. Ужас!

Давайте решать эту проблему.

Можно использовать свойство тега iframe под названием srcdoc (обязательно смотрите поддержку). Внутри этого свойства просто задаем разметку со ссылкой на плеер ютуба с параметром автоплей. Никакого JS (#nojs), только стандартный функционал браузера.

В результате получаем загрузку плеера только для тех, кто кликнул на плей, что нам и требовалось. И всего одно соединение для загрузки превью видео (картинку можно также сохранить себе на хостинг и исключить это единственное соединение).

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

Код на CodePen
👍23🔥10👏21
Мы готовим большой гайд по метрикам Core Web Vitals.

Выходит целых 8 сообщений на канал.
Нужна ли подробная информация с примерами про каждый из показателей?
Хотите ли вы получать информацию сразу или порционно по посту в день?
👍22🔥2👏2
❗️ Начинаем сегодня и в течение недели будем публиковать методы улучшения показателей Core Web Vitals.

Google анонсировал Web Vitals в 2019 году, а уже в 2021 году показатели Core Web Vitals стали влиять на выдачу в Google. Основные метрики Core Web Vitals - это LCP, FID и CLS, именно про них гугл выдает предупреждения в Google Webmaster Console.

Данные Web Vitals - это живые данные, которые получены и агрегированы на серверах Google от браузеров реальных пользователей. Google Chrome в фоновом режиме передает в Google данные о скорости посещенных сайтов. Показатели метрик, адреса страниц, данные об устройстве и взаимодействии со страницей. Данные усредняются и выводятся по 75-ому процентилю (не путать с квантилем). Это когда вычисляется значение так, чтобы 75% общих данных находились ниже этого предела.

Все данные можно получить через коннектор Chrome UX Report. Переходим, вводим сайт (с www и https) и нажимаем связать. Далее давим создать отчет и получаем графический отчет с историей изменения всех показателей (если данных достаточно).

Кроме основных показателей, которые описаны выше, мы увидим еще и другие данные, некоторые из них могут быть вам знакомы по отчетам Lighthouse, а некоторые совсем непонятные, которые собирает гугл, а это FCP, INP, TTFB, FP, Notification Permissions, DCL, OL и параметры распределения устройств и скорости соединениям: Device Distribution и Connect Distribution. Подробно их все обязательно разберем в течение этой недели.

Данные в отчете Chrome UX Report обновляются раз в месяц, тоесть данные всегда с отставанием, примерно в один месяц. Более точные данные за последние 28 дней (что тоже не моментально) можно найти в Google Pagespeed Insights, и в Chrome UX Report API. Быстро данные из этого API можно увидеть на сайте webvitals.ru.

🗓 Завтра разберем LCP, как основной показатель, отвечающий за скорость загрузки.

💬 Делитесь своими показателями и задавайте вопросы в комментариях. Помните, не бывает глупых вопросов.
👍10🔥2👏2
⚠️ Сегодня все внимание на LCP - продолжаем серию публикаций про Core Web Vitals.

🟢 Зеленая зона: до 2.5 секунд
🟡 Желтая зона: от 2.5 секунд до 4 секунд
🔴 Красная зона: более 4 секунд

LCP (Largest Contentful Paint) - Скорость загрузки основного контента, который занимает большую часть первого экрана страницы и является контрастным к фону. Так как мы говорим про Core Web Vitals, то следует учитывать какой элемент страницы является LCP-элементом, так как загрузка происходит с разных устройств с разным разрешением экрана, и где-то на первый экран может попадать больше контента и естественно, что элементы могут быть разными. Кроме того, для разных страниц LCP-элемент также может быть разным. Где-то вставлено небольшое изображение и LCP-элементом может являться большой заголовок, а где-то наоборот небольшой заголовок, но большое изображение, и уже изображение является LCP-элементом.

Большой показатель может свидетельствовать о том, что у пользователя есть проблема с отображением основного контента страницы, а это создает у пользователя иллюзию медленного интернета. Да, пользователь редко когда воспринимает медленным ваш сайт, чаще он будет думать, что тормозит интернет или устройство с которого он посетил ваш сайт. Так вот, если мы понимаем, что есть проблема с LCP, нам нужно в первую очередь понять, какой элемент является LCP-элементом. Для этого можно использовать отчеты Lighthouse, или Google Pagespeed Insights, который кстати тоже работает на Lighthouse. И уже после этого принимать решение, что делать.
👍12🔥2👏2
🧩 Улучшаем LCP

Если LCP-элементом является изображение, то нужно проверить, не отложено ли оно. Изображения, которые могут являться LCP-элементом ни в коем случае не откладываем. Далее максимально сжимаем это изображение. Для быстрого сжатия воспользуйтесь приложением, о котором мы писали ранее. Обязательно проверьте разрешение изображения. Часто бывает, что на первом экране изображение с зеркалки размером 6000х4000 пикселей, а то и больше, с весом 18 мб. Если его просто сжать и перевести в webp и avif, мы все равно получим 2-4 мегабайта данных, что очень много. Сжимайте изображение так, чтобы оно весило не более 100 кб. Меньше - лучше. Для повышения приоритета загрузки, если на странице много запросов, можно добавить <link rel="preload" as="image" href="/lcp.jpg">.

Если LCP - это текстовый тег, например h1, или p, то здесь нужно проверить, что шрифты загружены, и для них используется font-display:swap. Без этого до момента загрузки шрифта будет просто белый экран. Если шрифты подключаются из Google Fonts, то перечитате наши посты (раз, два, три). Если шрифт грузится с вашего хоста, используйте формат woff2 и добавьте именно его в прелоад: <link rel="preload" as="font" href="font.woff2" crossorigin>.

Если же LCP-элементом является div, у которого есть фоновое изображение и текстовое содержимое, то тут возникает проблема с приоритетом загрузки, и для его отображения нужно загрузить картинку и загрузить шрифт. Лучше всего переверстать такой блок так, чтобы использовался тег img, а не фоновое изображение. Это поможет браузеру определить очередность загрузки и LCP улучшится. Далее определяем новый LCP-элемент и заново пробегаем по алгоритму.

Из неочевидных возможностей улучшения показателя LCP на сайте - смещение фокуса. Например, можно добавить на фон контейнер div c контрастной заливкой и без какого-либо содержимого подложкой под весь первый экран с абсолютным позиционированием. Самое важное при смене фокуса - проработать изменение дизайна, тогда можно будет вообще убрать фотографию с первого экрана.
👍13🔥2👏2