Google PageSpeed Insights
Много информации про это уже написано, но некоторые моменты постоянно приходится «гуглить» и постоянно находятся новые варианты решения некоторых моментов. Чтобы не искать их постоянно — буду их добавлять сюда по мере возможности.
Первое что нужно сделать — это оптимизация изображений. Сделать это можно:
- Бесплатный вариант: MWS Image Resizer или Miniposter v2 by Sander
- Платный вариант: Miniposter v3 by Sander
Потом можно выполнить сжатие CSS/JS файлов, например, плагином DLE-ASSET
Следующим этапом можно выполнить сжатие HTML кода страницы — плагин тут.
Ну так же не стоит забывать об отложенной загрузки изображений, в ДЛЕ с 13-й версии lazyload.js включен в дистрибутив CMS.
Отложенная загрузка некоторых скриптов, например, яндекс.метрики.
Чаще всего данных действий вполне достаточно, чтобы показатель по гуглспид был выше 50-60 для мобильной версии, а для ПК версии может быть 80-90+.
Но иногда можно и подтянуть показатели ещё и другими способами. Более подробно о них сейчас и напишу.
Асинхронная загрузка JS (относится к разделу «Минимизируйте работу в основном потоке»)
Здесь всё предельно просто — нужно добавить к скриптам async или defer, чтобы было, например, так:<script async src="/libs.js"></script>
Асинхронную загрузку скриптов нельзя ставить на JQuery скрипты, на остальные скрипты можно это использовать, но всегда главное проверять работу скриптов после установки асинхронной загрузки, поскольку часто некоторые скрипты отказывают работать в таком режиме.Асинхронная загрузка CSS (так же относится к разделу «Минимизируйте работу в основном потоке»)
Здесь немного посложнее чем со скриптами… Но выход есть, и один из вариантов должен сработать.
Ранее я делал критический код стилей и выводил их непосредственно в коде шаблона, но, согласитесь, — это не всегда удобно, даже если делать это через {include… Поэтому продолжил поиски и тестирую их в данный момент на некоторых сайтах, в том числе и на данном блоге!Подключение шрифтов из CSS в main.tpl
<style> @font-face { font-family:'FontAwesome'; src:url('{THEME}/fonts/fontawesome-webfont.eot'); src:url('{THEME}/fonts/fontawesome-webfont.eot') format('embedded-opentype'),url('{THEME}/fonts/fontawesome-webfont.woff2') format('woff2'),url('{THEME}/fonts/fontawesome-webfont.woff') format('woff'),url('{THEME}/fonts/fontawesome-webfont.ttf') format('truetype'),url('{THEME}/fonts/fontawesome-webfont.svg') format('svg'); font-weight:normal; font-style: normal; font-display: swap; } </style> <link rel="preload" href="{THEME}/fonts/fontawesome-webfont.woff2" as="font" type="font/woff2" crossorigin>
Критический CSS код в main.tpl
(иногда с ним показатель гуглспид только уменьшается)
Сгенерировать его можно на сайте https://jonassebastianohlsson.com/criticalpathcssgenerator/. Полученный результат вставляем в main.tpl, а подключение CSS стилей переносим в самый низ страницы.Чтобы повысить производительность при прокрутке страницы, используйте флаг `passive` для прослушивателей событий прикосновения и колеса мыши.
Этот пункт относится к библиотеке jquery в DLE. Для исправления ошибки следовать инструкции гугла: найти в файле engine/classes/jsjquery.js все
и добавить по инструкцииaddEventListener
, {passive: true}
Должно получится примерно так:
Всего нужно сделать 2 замены, код такого типа
трогать не надо, только там, где нет третьего параметра.addEventListener(a,c,!0)
Иногда способ выше работает криво с некоторыми скриптами. Нашёл код, который скрывает данное предупреждение и не ломает скрипты другие на сайте:<script> jQuery.event.special.touchstart = { setup: function( _, ns, handle ) { this.addEventListener("touchstart", handle, { passive: !ns.includes("noPreventDefault") }); } }; </script>
Источник
Ещё один код:<script> jQuery.event.special.touchstart = { setup: function( _, ns, handle ) { this.addEventListener("touchstart", handle, { passive: !ns.includes("noPreventDefault") }); } }; jQuery.event.special.touchmove = { setup: function( _, ns, handle ) { this.addEventListener("touchmove", handle, { passive: !ns.includes("noPreventDefault") }); } }; jQuery.event.special.wheel = { setup: function( _, ns, handle ){ this.addEventListener("wheel", handle, { passive: true }); } }; jQuery.event.special.mousewheel = { setup: function( _, ns, handle ){ this.addEventListener("mousewheel", handle, { passive: true }); } }; </script>
ИсточникЗадайте правила эффективного использования кеша для статических объектов
Поскольку у меня сайт подключен к cloudflare, то решение нашёл такое: переходим в раздел Caching и в параметре «Browser Cache TTL» выбираем 1 год. Пробовал ставить и месяц и полгода, но данная рекомендация исчезла только с параметром в 1 год.
Если у вас нет, то можно попробовать включить кеш статических данных в .htaccess, что в корне сайта, добавив в самый верх:# сжатие text, html, javascript, css, xml: <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 </ifModule> # кеш браузера <ifModule mod_expires.c> ExpiresActive On #по умолчанию кеш в 5 секунд ExpiresDefault "access plus 1 days" # Включаем кэширование изображений и флэш на месяц ExpiresByType image/x-icon "access plus 1 month" ExpiresByType image/jpeg "access plus 4 weeks" ExpiresByType image/png "access plus 30 days" ExpiresByType image/gif "access plus 43829 minutes" ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds" # Включаем кэширование css, javascript и текстовых файлоф на одну неделю ExpiresByType text/css "access plus 604800 seconds" ExpiresByType text/javascript "access plus 604800 seconds" ExpiresByType application/javascript "access plus 604800 seconds" ExpiresByType application/x-javascript "access plus 604800 seconds" # Включаем кэширование html и htm файлов на один день ExpiresByType text/html "access plus 43200 seconds" # Включаем кэширование xml файлов на десять минут ExpiresByType application/xhtml+xml "access plus 600 seconds" # Нестандартные шрифты сайта ExpiresByType application/x-font-ttf "access plus 1 month" ExpiresByType font/opentype "access plus 1 month" ExpiresByType application/x-font-woff "access plus 1 month" ExpiresByType application/x-font-woff2 "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" ExpiresByType application/vnd.ms-fontobject "access plus 1 month" </ifModule>
Другой код://Пример фрагмента .htaccess (из плагина FastestCache) для решения ошибки "Задайте правила эффективного использования кеша для статических объектов" в PageSpeed //это просто пример! не копируйте его на свой сайт! //в данном примере задано время кеширования 1 Год // обычно это даёт + 2-4 балла по PageSpeed //© Калинский Евгений aka seojacky (https://t.me/big_jacky) //По вопросам оптимизации сайтов по требованиям PageSpeed пишите в Telegram https://t.me/big_jacky /* * Мои плагины для ускорения сайта: * True Lazy Analytics https://wordpress.org/plugins/true-lazy-analytics/ * Helper Lite for PageSpeed https://wordpress.org/plugins/helper-lite-for-pagespeed/ */ # BEGIN LBCWpFastestCache <FilesMatch "\.(webm|ogg|mp4|ico|pdf|flv|jpg|jpeg|png|gif|webp|js|css|swf|x-html|css|xml|js|woff|woff2|otf|ttf|svg|eot)(\.gz)?$"> <IfModule mod_expires.c> AddType application/font-woff2 .woff2 AddType application/x-font-opentype .otf ExpiresActive On ExpiresDefault A0 ExpiresByType video/webm "access plus 1 year" ExpiresByType video/ogg "access plus 1 year" ExpiresByType video/mp4 "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/jpg "access plus 1 year" ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/ico "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType text/css "access plus 1 year" ExpiresByType text/javascript "access plus 1 year" ExpiresByType application/javascript "access plus 1 year" ExpiresByType application/x-javascript "access plus 1 year" ExpiresByType application/font-woff2 "access plus 1 year" ExpiresByType application/x-font-opentype "access plus 1 year" ExpiresByType application/x-font-truetype "access plus 1 year" ExpiresByType application/pdf "access plus 1 year" </IfModule> <IfModule mod_headers.c> Header set Expires "max-age=A10368000, public" Header unset ETag Header set Connection keep-alive FileETag None </IfModule> </FilesMatch> # END LBCWpFastestCache
Источник
Ещё один код:<IfModule mod_expires.c> ExpiresActive On ExpiresDefault «access 7 days» ExpiresByType application/javascript «access plus 1 year» ExpiresByType text/javascript «access plus 1 year» ExpiresByType text/css «access plus 1 year» ExpiresByType text/html «access plus 7 day» ExpiresByType text/x-javascript «access 1 year» ExpiresByType image/gif «access plus 1 year» ExpiresByType image/jpeg «access plus 1 year» ExpiresByType image/png «access plus 1 year» ExpiresByType image/jpg «access plus 1 year» ExpiresByType image/x-icon «access 1 year» ExpiresByType application/x-shockwave-flash «access 1 year» </IfModule> <ifModule mod_headers.c> <filesMatch «\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$»> Header set Cache-Control «max-age=2592000, public» </filesMatch> <filesMatch «\.(css|js)$»> Header set Cache-Control «max-age=2592000, public» </filesMatch> <filesMatch «\.(xml|txt)$»> Header set Cache-Control «max-age=172800, public, must-revalidate» </filesMatch> <filesMatch «\.(html|htm|php)$»> Header set Cache-Control «max-age=172800, private, must-revalidate» </filesMatch> </ifModule> <IfModule mod_setenvif.c> BrowserMatch «MSIE» force-no-vary BrowserMatch «Mozilla/4.[0-9]{2}» force-no-vary </IfModule>
ИсточникКеширование файлов со сторонних ресурсов
Не ко всем файлам это может быть примерено, но всё же часть внешних файлов можно пропустить через свой сервер, и кеш будет выставлен согласно настройке сервера или настройкам клайдфларе. Суть метода:- Создаем PHP файл в корне сайта с содержимым:
<?php function downloadJs($file_url, $save_to) { $content = file_get_contents($file_url); file_put_contents($save_to, $content); } // Указываем URL, затем папку от корня сайта и имя файла с расширением. // Проверьте чтобы на папке были права на запись 777/755 // Метрика downloadJs('https://mc.yandex.ru/metrika/watch.js', realpath("./js") . '/watch.js'); // Google Analytics downloadJs('http://www.google-analytics.com/analytics.js', realpath("./js") . '/analytics.js'); // Для скриптов без расширения downloadJs('http://code.jivosite.com/script/widget/NuT1gBLsC6', realpath("./js") . '/NuT1gBLsC6'); ?>
- Создаем папку js в корневой директории сайта.
Для проверки работы скрипта — запускаем этот PHP файл, и в папке js должны будут появится указанные файлы.
Данным методом сегодня избавился от файла tag.js и файлов шрифтов от гугла. Файл watch.js нигде в коде страницы не указан, watch.js. У себя данный файл нашёл в коде файла шаблона share.js.
Если вы захотите так же прописать файлы шрифтов от гугла, то после этого нужно будет строку нужного шрифта заменить например на код
где rubik — это имя файла, которые вы прописали в PHP скрипте.<link href="/js/rubik" rel="preload">
- Далее нужно поставить данный файл на CRON, например строкой:
wget -q -O - /dev/null https://site/downloadjsfile.php >/dev/null 2>&1
Строка подключения на крон может отличаться в зависимости от настроек крона. Если данная команда не сработает — погуглите или обратитесь к справке вашего хостера или в ТП за помощью.
Источник
- Создаем PHP файл в корне сайта с содержимым:
Яндекс метрика и гуглспид
Подробнее тутИсправление шрифтов гугл
Добавить к строке подключения шрифта
Если это не поможет, то можно использовать способ ниже.&display=swap
Асинхронная загрузка шрифтов Google Fonts
При проверке скорости сайта goolgle speed insight или gtmertrix нам говорят, что шрифты гугл блокируют содержимое страницы и их необходимо загрузить позже.<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
Делаем все с помощью скрипта fonfaceobserver, который также загружаем асинхронно (весит всего 5 Кб в несжатом виде).
Качаем здесь: https://github.com/bramstein/fontfaceobserver/
Сам скрипт кладем например в папку /JS. Получится, что доступен он по ссылке «ваш сайт»/js/fontfaceobserver.js
Далее в header добавляем вместо ссылки на гугл шрифт (для начала просто закомментируйте его)<!--подключаем шрифт--> <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin> <style> @import url(//fonts.googleapis.com/css?family=Ваш шрифт и начертания); /* шрифт по умолчанию, до тех пор пока не подгружен новый шрифт */ .fonts-loaded { body { font-family: Ваш шрифт, sans-serif; } } </style> <script> var script = document.createElement('script'); script.async = true; script.src = 'https://raw.githubusercontent.com/bramstein/fontfaceobserver/master/fontfaceobserver.js'; script.onload = function () { // инициализация var font = new FontFaceObserver('Ваш шрифт'); font.load().then(function () { document.documentElement.className += " fonts-loaded"; }); }; document.head.appendChild(script); </script>
ИсточникЗагрузка CSS
<link rel="alternate stylesheet" href="mystyles.css" onload="this.rel='stylesheet'">
Такой метод нужно использовать не ко всем CSS стилям, а только к тем, которые не важны для начальной отрисовки страницы, иначе будет кривая загрузка страницы, пока не прогрузятся все стили и скрипты.
Источник
Лучше использовать:<link rel="preload" href="{THEME}/css/jquery.lazyloadxt.spinner.css" as="style" onload="this.rel='stylesheet'">
Ещё один вариант для решения пункта «удалите ресурсы блокирующие отображение загрузки». Применение loadCSS.
Пример кода:<!DOCTYPE html> <html> <head> <style>/* header.css */</style> <link rel="preload" as="style" href="font.css"> <link rel="preload" as="style" href="article.css"> <link rel="preload" as="style" href="comments.css"> <link rel="preload" as="style" href="about.css"> <link rel="preload" as="style" href="footer.css"> <noscript> <link rel="stylesheet" href="font.css"> <link rel="stylesheet" href="article.css"> <link rel="stylesheet" href="comments.css"> <link rel="stylesheet" href="about.css"> <link rel="stylesheet" href="footer.css"> </noscript> </head> <body> <header class="header"></header> <main class="article"></main> <section class="comments"></section> <section class="about"></section> <footer class="footer"></footer> <script> importCSS('font.css', 0, true); importCSS('article.css'); importCSS('comments.css'); importCSS('about.css'); importCSS('footer.css'); </script> </body> </html>
Не забываем подключить loadCSS.js в секцию head.
ИсточникФункция build_css в DLE
В файле engine/modules/functions.php найти$css_array[] = "<link href=\"{$config['http_home_url']}{$value}?v={$v}\" rel=\"stylesheet\" type=\"text/css\">";
и заменить на$css_array[] = "<link rel=\"preload\" href=\"{$config['http_home_url']}{$value}?v={$v}\" as=\"style\" onload=\"this.rel='stylesheet'\">";
Главное обязательно потом проверить все стили, на которые могут повлиять css файлы, выводимы в ДЛЕ по умолчанию.Ещё один вариант отложенной загрузки Яндекс Мерики
В комментариях к коду всё подробно расписано, так что проблем возникнуть не должно.<script> ( function () { 'use strict'; // Флаг, что Метрика уже загрузилась. var loadedMetrica = false, // Ваш идентификатор сайта в Яндекс.Метрика. metricaId = 123456789, // Переменная для хранения таймера. timerId; // Для бота Яндекса грузим Метрику сразу без "отложки", // чтобы в панели Метрики были зелёные кружочки // при проверке корректности установки счётчика. if ( navigator.userAgent.indexOf( 'YandexMetrika' ) > -1 ) { loadMetrica(); } else { // Подключаем Метрику, если юзер начал скроллить. window.addEventListener( 'scroll', loadMetrica, {passive: true} ); // Подключаем Метрику, если юзер коснулся экрана. window.addEventListener( 'touchstart', loadMetrica ); // Подключаем Метрику, если юзер дернул мышкой. document.addEventListener( 'mouseenter', loadMetrica ); // Подключаем Метрику, если юзер кликнул мышкой. document.addEventListener( 'click', loadMetrica ); // Подключаем Метрику при полной загрузке DOM дерева, // с "отложкой" в 1 секунду через setTimeout, // если пользователь ничего вообще не делал (фоллбэк). document.addEventListener( 'DOMContentLoaded', loadFallback ); } function loadFallback() { timerId = setTimeout( loadMetrica, 1000 ); } function loadMetrica( e ) { // Пишем отладку в консоль браузера. if ( e && e.type ) { console.log( e.type ); } else { console.log( 'DOMContentLoaded' ); } // Если флаг загрузки Метрики отмечен, // то ничего более не делаем. if ( loadedMetrica ) { return; } (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym"); ym( metricaId, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); // Отмечаем флаг, что Метрика загрузилась, // чтобы не загружать её повторно при других // событиях пользователя и старте фоллбэка. loadedMetrica = true; // Очищаем таймер, чтобы избежать лишних утечек памяти. clearTimeout( timerId ); // Отключаем всех наших слушателей от всех событий, // чтобы избежать утечек памяти. window.removeEventListener( 'scroll', loadMetrica ); window.removeEventListener( 'touchstart', loadMetrica ); document.removeEventListener( 'mouseenter', loadMetrica ); document.removeEventListener( 'click', loadMetrica ); document.removeEventListener( 'DOMContentLoaded', loadFallback ); } } )() </script>
Код почищенный от комментариев:<script> ( function () { 'use strict'; var loadedMetrica = false, metricaId = 123456789, timerId; if ( navigator.userAgent.indexOf( 'YandexMetrika' ) > -1 ) { loadMetrica(); } else { window.addEventListener( 'scroll', loadMetrica, {passive: true} ); window.addEventListener( 'touchstart', loadMetrica ); document.addEventListener( 'mouseenter', loadMetrica ); document.addEventListener( 'click', loadMetrica ); document.addEventListener( 'DOMContentLoaded', loadFallback ); } function loadFallback() { timerId = setTimeout( loadMetrica, 1000 ); } function loadMetrica( e ) { if ( e && e.type ) { console.log( e.type ); } else { console.log( 'DOMContentLoaded' ); } if ( loadedMetrica ) { return; } (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym"); ym( metricaId, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); loadedMetrica = true; clearTimeout( timerId ); window.removeEventListener( 'scroll', loadMetrica ); window.removeEventListener( 'touchstart', loadMetrica ); document.removeEventListener( 'mouseenter', loadMetrica ); document.removeEventListener( 'click', loadMetrica ); document.removeEventListener( 'DOMContentLoaded', loadFallback ); } } )() </script>
ИсточникОтложенная загрузка счетчика Liveinternet
<!--LiveInternet counter--><script type="text/javascript"> document.write('<a href="//www.liveinternet.ru/click" '+ 'target="_blank"><img src="//counter.yadro.ru/hit?t16.6;r'+ escape(document.referrer)+((typeof(screen)=='undefined')?'': ';s'+screen.width+'*'+screen.height+'*'+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+';u'+escape(document.URL)+ ';h'+escape(document.title.substring(0,150))+';'+Math.random()+ '" alt="" title="LiveInternet: показано число просмотров за 24'+ ' часа, посетителей за 24 часа и за сегодня" '+ 'border="0" width="88" height="31"><\/a>') </script><!--/LiveInternet-->
заменить на<!--LiveInternet counter--> <script type="text/javascript">new Image().src = "https://counter.yadro.ru/hit?r"+escape(document.referrer)+((typeof(screen)=="undefined")?"" :";s"+screen.width+"*"+screen.height+"*" + (screen.colorDepth?screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+ ";h"+escape(document.title.substring(0,80))+ ";" +Math.random();</script> <!--/LiveInternet--> <!--LiveInternet logo--> <a href="https://www.liveinternet.ru/click" target="_blank"> <img data-src="https://counter.yadro.ru/logo?16.6" border="0" width="88" height="31" alt="" title="Показано количество просмотров и посетителей"/> </a> <!--/LiveInternet-->
Отложенная загрузка рекламных блоков РСЯ, disqus
div с идентификационным номером вставляем в HTML-код вашего сайта между тегами
и<body>
в том месте, где должен отображаться рекламный блок.</body>
А содержимое тега
заворачиваем в нашу конструкцию и помещаем ее в footer сайта.<script></script>
<script> var event_status = false; // Статус события (ещё не произошло) window.addEventListener("load", function() { // Страница загрузилась полностью ["mouseover", "click", "scroll"].forEach(function(event) { window.addEventListener(event, function() { // Произошло нужное событие (mouseover, click или scroll) с объектом window if(!event_status) { // ВАШ КОД window.yaContextCb.push(()=>{ Ya.Context.AdvManager.render({ renderTo: 'yandex_rtb_R-A-588461-2', blockId: 'R-A-588461-2' }) }) event_status = true; // Статус события (произошло) } }, { once: true }); }); }); </script>
Так же в данный код можно добавить и другие рекламные блоки из script.
Источник
ИсточникОтложенная загрузка рекламы Google Adsense
Заменить код<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3964770956959018" crossorigin="anonymous"></script>
на следующий<script type="text/javascript">//<![CDATA[ var adsenseLazyload = false; window.addEventListener("scroll", function(){ if ((document.documentElement.scrollTop != 0 && adsenseLazyload === false) || (document.body.scrollTop != 0 && adsenseLazyload === false)) { (function() { var ad = document.createElement('script'); var att = document.createAttribute('data-ad-client'); att.value = 'ca-pub-3964770956959018'; ad.setAttributeNode(att ); ad.async = true; ad.src = 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js'; var sc = document.getElementsByTagName('head')[0]; sc.parentNode .insertBefore(ad, sc); })(); adsenseLazyload = true; } }, true) //]]></script>
где 3964770956959018 - это идентификатор вашего рекламного блока.
Источник #1 Источник #2Уменьшите влияние стороннего кода (googletagmanager.com)
Заменить код:<!-- Global site tag (gtag.js) - Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());</pre> gtag('config', 'UA-XXXXXXXX'); </script>
на<script> var fired = false; window.addEventListener('scroll', () => { if (fired === false) { fired = true; setTimeout(() => { // Пример подключения скрипта, который просто использует вставку через <script src="..."></script> // В данном случае - это пример вставки гугл аналитикс var GTMObject = document.createElement("script"); GTMObject.src = 'https://www.googletagmanager.com/gtag/js?id=<ID>'; GTMObject.async = true; document.getElementsByTagName('head')[0].appendChild(GTMObject); window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', '<ID>'); }, 5000); } },{passive: true}); </script>
ИсточникУдалите неиспользуемый код jаvascript - recaptcha v3
Отложенная загрузка скрипта рекапчи, после скролинга станицы скрипт будет загружен. Установка через плагины.
[attachment=227:recaptcha-v3-scrolling.zip]
ИсточникОтложенная загрузка виджета ВК, статистики гугла, яндекса и ли
Подробнее тут (не проверена работа скриптов)
Скопировал код на склучай, если не будет сайт доступен.<!-- Див в котором будет отображаться виджет --> <div id="vk_community_messages"></div> <script type="text/javascript"> // откладываем по времени setTimeout(function(){ // создаем элемент script и добавляем его асинхронно в DOM var VKO = document.createElement("script"); VKO.src = 'https://vk.com/js/api/openapi.js'; VKO.async = true; document.getElementsByTagName('head')[0].appendChild(VKO); // подгружаем инициализацию виджета на загрузку VKO.onload = function(){ // код, который дает сам виджет ВК VK.Widgets.CommunityMessages("vk_community_messages", 127607773, {expanded: "1",tooltipButtonText: "Есть вопрос?"}); }; },5000); // здесь указывается время в миллисекундах 5000 мс = 5 секунд </script> <script type="text/javascript"> var fired = false; window.addEventListener('scroll', () => { if (fired === false) { fired = true; setTimeout(() => { // Yandex.Metrika counter (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); ym(13698373, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); // Global site tag (gtag.js) - Google Analytics var GTMObject = document.createElement("script"); GTMObject.src = 'https://www.googletagmanager.com/gtag/js?id=UA-36888304-1'; GTMObject.async = true; document.getElementsByTagName('head')[0].appendChild(GTMObject); window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'UA-36888304-1'); // LiveInternet counter new Image().src = "//counter.yadro.ru/hit?r"+ escape(document.referrer)+((typeof(screen)=="undefined")?"": ";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+ ";h"+escape(document.title.substring(0,80))+ ";"+Math.random(); }, 2000); } }); Copied
Отложенная загрузка vk_groups
Код<script type="text/javascript"> VK.Widgets.Group("vk_groups", {mode: 1, width: 280, height: 400, color1: "FFFFFF", color2: "000000", color3: "5181B8"}, 208692565); </script>
нужно заменить на<script> let ok = false; window.addEventListener('scroll', function() { if (ok === false) { ok = true; setTimeout(() => { let script = document.createElement('script'); script.src = 'https://vk.com/js/api/openapi.js?168'; document.getElementById('vk_groups').after(script); script.onload = function() { VK.Widgets.Group("vk_groups", {mode: 3, width: "auto"}, 208692565); } }, 1000) } }); </script>
Источник - не помню 😊 Но код рабочий и гуглспид не ругается на виджет группы ВК.Предзагрузите изображение для элемента "Отрисовка самого крупного контента"
<link rel="preload" as="image" href="img.jpg" />
Элемент "Отрисовка самого крупного контента"
В head:[aviable=main|cat|xfsearch]{custom limit="2" order="date" sort="desc" template="main-img-head"}[/aviable] [aviable=showfull]<link rel="preload" as="image" href="[xfvalue_poster]">[/aviable]
main-img-head.tpl:<link rel="preload" as="image" href="[xfvalue_poster]">
Largest Contentful Paint
Здесь для сторонних ресурсов стоит использовать preconnect или dns-prefetch.<link rel="dns-prefetch" href="https://mc.yandex.ru"> <link rel="preconnect" href="https://mc.yandex.ru" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin> <link rel="dns-prefetch" href="//fonts.googleapis.com">
Более подробно по данным и аналогичным тегам - тут.Устраните ресурсы, блокирующие отображение + fonts.googleapis.com
<link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans:300&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript><link href="https://fonts.googleapis.com/css?family=Open+Sans:300&display=swap" rel="stylesheet" type="text/css"></noscript>
ИсточникМинимизируйте работу в основном потоке + js
Поставить все возможные скрипты на async. После этого нужно проверять чтобы все скрипты на сайте работали без ошибок, т.к. не всё можно поставить на асинхронную загрузку.Изображение, которое отображается при отрисовке самого крупного контента, загружено с задержкой
Нужно убрать на это изображение
при data-src данной проблемы замечено небыло. Так опытным путем и выявил данную проблему, потому что в поисковике по конкретной фразе данной проблемы было всего пару страниц, в которых ничего не сказано о решении данной проблемы.loading=lazy
Ещё один вариант отложенной загрузки внешних скриптов js
<script> let ok = false; window.addEventListener('scroll', function() { if (ok === false) { ok = true; setTimeout(() => { let script = document.createElement('script'); script.src = 'https://site/file_id.js'; document.getElementById('id-block-id').after(script); }, 1000) } }); </script> <div id="id-block-id"></div>
Скрипт проверил на одной рекламе - +40 показатель по гуглспид сразу прибавляет, т.к. не загружает скрипт сарзу при загрузке основного контента. Подойдёт не под все коды реклам, нужно проверять каждый случай на корректное отображение вывода рекламы.Чистка fontawesome.css от лишних иконок
Подробнее тутпродолжение следует…
изучаемая и проверяемая инфа:
для шрифтов: https://techblog.sdstudio.top/blog/pagespeed-insights-nastroyte-predvaritel-nuyu-zagruzku-klyuchevyh-zaprosov
https://habr.com/ru/post/436966/
https://fooobar.com/questions/313160/how-to-load-css-asynchronously
https://github.com/filamentgroup/loadCSS
UPD
https://webformyself.com/proverka-proizvoditelnosti-sajta-s-lighthouse/
LazyLoad script: https://gist.github.com/mihdan/4a6cebc2614a62797b9d7806a628af0b