Новий LCP hack, або Як «розвести» Google на дві секунди
Усім привіт, я Айвазян Армен, Front-end Engineer в компанії АМО. Я присвячую багато часу Core Web Vitals показникам, оскільки один з наших проєктів — це великий медіасайт, благополуччя якого залежить зокрема від «Google циферок». Я думав, що мене вже не можна здивувати нічим, що повʼязано з Core Web Vitals, але в певний момент ми помітили, що маємо серйозну негативну динаміку показника LCP. І це за умови, що ніяких із цим повʼязаних змін не проводили; більше того, у нас реалізований LCP hack. Але показник падав у «червону зону» місяць за місяцем.
У цій статті я хочу розказати, куди завело мене детективне розслідування і яким був фінал (обіцяю неочікуваний поворот сюжету 🙂). Також я описую практичний гайд зі створення нового LCP hack. Можливо, ця стаття стане в пригоді людям, які зіштовхнуться з такою ж «LCP-проблемою» (або просто тим, хто любить гостросюжетні історії, де все найцікавіше ховається в деталях).
Дисклеймер: я розумію, що обман Google для підвищення показнику «балів перформансу» (і користувацький досвід у такій ситуації) — це доволі холіварна тема, яка заслуговує, як мінімум, окремої статті, але тут я хочу лише поділитися способом покращення LCP для людей у яких, як і в мене, є необхідність це зробити. А чи використовувати це, чи ні — дуже залежить від контексту проєкту і багатьох інших факторів.
Підґрунтя. Що таке LCP?
Простими словами, Largest Contentful Paint (LCP) — це час, який минає від початку першого завантаження сторінки до завершення рендеру найбільшого елементу, що знаходиться в області перегляду (viewport) користувача.
LCP — це спосіб від Google дізнатися, як довго рендериться основний контент вашої сторінки. Логіка така: якщо найбільший видимий елемент на сторінці показаний юзеру, це означає, що основний контент завантажився (погоджуюсь, звучить доволі суперечливо, але кращого методу оцінки Google поки не придумав). До речі, недосконалість такого підходу доводить існування такого собі LCP hack (про який поговоримо далі).
У часи, коли динозаври ходили Землею, дехто намагався використовувати FMP та Speed Index для заміру чогось подібного, але це було важко та неточно. (Не варто плутати з дуже схожим FCP (який показує час рендеру будь-якого першого видимого елементу, яким може бути і звичайний лоадер).
Шкала «Гарного — поганого LCP».
Цікавий факт: найбільший видимий елемент може змінюватися в міру завантаження сторінки. Як тільки завантажується черговий фрейм, браузер відправляє запис largest-contentful-paint, який відстежує найбільший елемент. І якщо він більший за поточний — заміняє його. Відстежування завершується після першої взаємодії (прокрутка, клік і подібне) користувача зі сторінкою.
Ґрунт. Що таке LCP hack?
LCP hack — це старенький спосіб «обдурити» Google, відрендивши на сторінці легкий, невидимий для юзера, але дуже великий елемент (назвемо його фейком). Таким способом у largest-contentful-paint потрапляє фейк, а коли починається рендер реально найбільшого елементу, він під час порівняння однаково не потрапляє в largest-contentful-paint, тому Google стежить лише за фейком і формує показник LCP на його основі.
Є пару варіантів реалізації. Розкажу про найпопулярніший. Беремо тег img
, в style
задаємо щось на кшталт:
pointer-events: none; position: absolute; top: 0; left: 0; width: 99vw; height: 99vh; max-width: 99vw; max-height: 99vh;
А в src
якийсь прозорий base64
. Задаємо дуже велике значення для атрибутів width
та height
і отримуємо:
<img width="2000" height="2000" style="pointer-events:none;position:absolute;top:0;left:0;width:99vw;height:99vh;max-width:99vw;max-height:99vh" src="data:image/svg+xml;base64,..." role="presentation" alt="some-alt" >
Щоб протестувати наш hack, скористаємося найпростішим і найшвидшим способом вимірювання показників Core Web Vitals, а саме Lighthouse вкладкою в Chrome DevTools (і перед тим, як багато хто з вас справедливо почне писати мінуси такого заміру і про локальну машину, зауважу: цей спосіб я використовую лише для простої демонстрації результату до / після, де всі ці деталі можна опустити). Проганяємо піддослідну сторінку без hack, спускаємося до вкладки LCP та дивимося на результат:
Очікувано бачимо найбільший елемент на першому viewport. Тепер додамо наш hack за ідентичних вхідних даних:
Супер, спрацювало! І якщо ми порівняємо вагу цих двох елементів, різниця буде просто колосальною (105KB проти 300B). Але Google однаково думає, що найбільший елемент — це наш hack. Ідеальний злочин 🙂. Як-то кажуть, все геніальне — просто!
Але як і будь-яка хороша історія, ця також мала свій фінал. Й одного дня ми побачили негативну динаміку з LCP на наших сайтах...
Основний квест
Завʼязка: мені надсилають тікет з проблемою того, що в нас починає падати LCP-показник без видимої причини.
Дисклеймер: хто не знає та кому цікаво, як всі ці графіки будувати, де брати дані та інше — ласкаво прошу в коментарі, надам усю інформацію.
Вивантажуємо звіт з LCP нашого сайту за допомогою lookerstudio
:
Дані, які можуть викликати серйозну депресію в Front-end спеціаліста, який стежить за Core Web Vitals показниками сайту.
Ось із цього скрина й розпочалася моя пригода.
Але ми не здаємося. Подивімось на більш детальні дані та побудуємо графік на основі page speed
Ще більш разючий графік, на якому бачимо, що біда сталась на початку квітня. Це вже якась інформація, нумо розбиратися далі. Перше припущення, яке напрошується відразу: щось не так з hack. Це можна легко перевірити, подивившись вкладку Lighthouse і спустившись до LCP.
Найбільший елемент визначено як реальне зображення на сайті, отже, припущення правильне — hack більше не працює. Але що ж сталося? Адже рішення проблеми майже завжди можна знайти в причині цієї проблеми. Тому потрібно відшукати корінь.
Шукаємо релізи Chrome (бо тільки користувачі цього браузеру потрапляють у вибірку для формування Performance показнику від Google) у період, який нас цікавить. Знаходимо статтю про нову версію Chrome 112, яка випустилася якраз на початку квітня. Ні слова про LCP, але ж це не може бути просто збігом? Занурюємося глибше та знаходимо в chromium запис про зміну виміру LCP саме в 112 версії!
На основі цього заголовку та абзацу
ставимо перед собою дві цілі:
- збільшити вагу нашої картинки-hack;
- спробувати переконати Google, що в нашій картинці-hack є контент.
Притримуючись ключового принципу «Що простіше, то краще»:
- Беремо реальну svg-картинку (головне, аби вона була простенька, а конвертований варіант — не дуже важким).
- Робимо всі вектори прозорими.
- Конвертуємо в
base64
. - Вітаю, ви прекрасні!
Тепер ми маємо повністю непомітну для користувача, але «контентну» (ніхто ж не казав, що вона не може бути прозора, хе-хе) картинку, яка важить приблизно 3КB (шляхом величезної кількості спроб і страждань вивів саме такий мінімально необхідний розмір для LCP hack).
Біжимо перевіряти:
Чудово! Працює очікувано — допомогло. Але уважний читач може зауважити: а де ж неочікуваний поворот і гострий сюжет?
Як і обіцяв, розповідаю. Поки я відкорковував пляшечку соку, щоб відсвяткувати свою чудову роботу, вирішив заглянути в лабораторний репорт pagespeed.web.dev
. І побачив, що Google правильно бачить старий hack.
Так що ж це виходить? Невже проблема не в цьому? Невже локальний замір просто дав збій, і вся теорія з
Мене чекало чергове занурення в інтернет та вичитка всіх тематичних і не дуже форумів. Урешті-решт, витративши пару годин, купу своїх нервів, не знайшовши нічого толкового й майже покинувши цю справу, я випадково глянув на те, який саме User Agent використовує лабораторний скринер pagespeed.web.dev
.
Дрібним текстом написано про завітну 109 версію! Це знову дає сили і мізерну надію на те, що лабораторний скринер ще просто не оновив логіку трекання LCP і бачить наш hack. Але реальні люди частково оновлюють або оновили свої Chrome і збирають польові дані вже за новою логікою (оминаючи наш hack).
Хоч це й на рівні фантастики, але все ж має сенс, і ми легко (ну майже, бо Chrome офіційно не дає скачати і не підтримує старі свої версії) можемо це перевірити за допомогою такого інструменту як Docker.
- Запускаємо Docker.
- Піднімаємо image Chrome 109.
- Перевіряємо User Agent на нашій «віртуальній машині».
(ідентичний з Google-скринером)
4. Заходимо на нашу статтю і проганяємо через lighthouse
, і що ж ми бачимо? Еврика! Бачимо старий hack, який зчитується як найбільший елемент.
Це доводить те, що лабораторний скринер pagespeed
використовує справді ту версію, яка ще не вміє оминати його, але найголовніше, що це підтверджує правильність нашої теорії, і ми можемо спасти LCP!
Результати та висновок
Випуск фіксу відбувся 10 серпня. І ось результат, який ми бачимо вже 12 серпня:
Спостерігається позитивна динаміку далі. Станом на 13 вересня показник опустився до 1,6 секунд порівняно з 3,5 секундами, що були!
Отже, новий LCP hack подіяв і має право на життя.
Висновок дуже простий і короткий: будьте відкритими до нового, підходьте креативно до вирішення задач. Не відкидайте навіть найшаленіші теорії, якщо вони мають раціональне підґрунтя. Також завжди придивляйтесь до деталей — вони важливі.
15 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів