PageSpeed Insights. Оптимизация страниц сайта под скорость его загрузки(на примере WordPress)

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

Содержание

PageSpeed Insights

Это один из многих анализаторов времени загрузки страницы. Анализатор(а не измеритель) потому, что он

PageSpeed Insights

оценивает время загрузки в своих “попугаях”(если об основной оценке).

Несмотря на это, этот инструмент является основным для проверки оптимизации сайта; как мне кажется – потому, что разработан Google`ом(ну и удобство – кратко и по делу, в многих альтернативных ресурсов наоборот – много, подробно и хз что с этим делать).

Исходная точка

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

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

И здесь мое размышление(к делу не относящееся):

Принято говорить: “оптимизация страницы приводит к ускорению загрузки сайта”. Моя мысль: может ли руль изменить характеристики двигателя?..

Итак, к чему это? А не к чему! Если соблюдать терминологию(из мысли) то: двигатель это девайс пользователя(т.е. твой или сервера поисковика…), сайт – это, нет , не машина… это водитель! страница это машина. Что я хочу сказать – оптимизация сайта – это обучение водилы крутить баранку, проходить виражи с минимальной потерей времени. Да, главным двигателем здесь является сервер, на котором размещен сайт и который рендерит страницы – однако, в большинстве случаев, его оптимизировать мы не сможем.

Лады, перейдем к сути. На данный момент(перед началом оптимизации) я имею такие показатели:

27 попугаев
показатели перед стартом

Еще я забыл упомянуть – я буду ориентироваться на показатели для мобильных устройств. Объясню это следующим образом: производя поиск(даже если у пользователя ультра-супер-пупер ПК, мощности которого, все равно, не задействуются в поиске), первыми будут подняты те страницы, которые не только более соответствуют запросу, но и для поднятия которых требуется меньше ресурсов. К примеру, эта страница по показателям ПК имеет 77 попугаев(уже! без оптимизации!).

Чем крут PageSpeed еще – это объяснением, как оптимизировать. Вот мои проблемы

Начальные проблемы
Начальные проблемы

В принципе, это полный спектр проблем, которые может иметь сайт… а нет, вру! На одном сайте было “Сократите время ответа сервера”, поскольку к серверу никак притронуться я не мог – я переключил только версию PHP на 7.0(она дала наибольшее ускорение).

Я пошарился по странице(а именно в инструментах разработчика в хроме) и нашел основные тормоза. В первых, я использую библиотеку ace.js для раскрашивания кода, во-вторых – как и на многих сайтах, есть jquery; также, есть скрипты темы, скрипты для соцсетей и много стилей.

Первая беда – “Устраните ресурсы, блокирующие отображение”

Чтобы понять суть этой проблемы – нужно понять как браузер рендерит страницу: Этап 1 – загрузка HTML-разметки. Затем происходит парсинг и выстраивание DOM(Document Object Model); на этой стадии, каждый внешний файл вызывает блокировку процесса до момента полного его прочтения и осознания. Файлы JS блокируют выполнение во всех браузерах, CSS же(по словам разработчика Yahoo! – Stoyan Stefanov) не блокируют в серии IE браузеров, не блочат в Firefox.

Однако, перейдем к проблеме – открыв подробности о ней, виден совет:

Некоторые ресурсы блокируют первую отрисовку страницы. Рекомендуем встроить критическую часть данных JS/CSS в код HTML и отложить загрузку остальных ресурсов. Подробнее…

Скажу более того, здесь же и ссылка на плагины для WordPress, которыми можно оптимизировать этот(да и прочие) параметры. НО! Используя их, мне не удалось побороть эту проблему – по-этому я прибег к кодингу.

Начнем-ка! в начале,прежде чем что-то ломать, глянем на вкладку Coverage(если отсутствует – кликни по трем точкам у начала панели) в Google Crome DevTools

chrome web dev tools

с целью увидеть, что используется из активов. С ходу увидим в каких файлах использование кода равно 0 – в колонке “Unused Bytes” показатель 100%. в. Здесь ты можешь предположить, что я буду их снимать с регистрации, да! – именно так я и поступлю! К примеру, у меня нулевой файл имеет такую ссылку /wp-content/plugins/contact-form-7/includes/css/styles.css; находим стпоку в исходном коде страницы

<link rel='stylesheet' id='contact-form-7-css'  href='/wp-content/plugins/contact-form-7/includes/css/styles.css?ver=5.4' media='all' />

id=’contact-form-7-css’, что значит слаг – ‘contact-form-7’ и тип файла стили. Это знание позволит мне снять этот файл с регистрации на нужной мне странице

    add_action('wp_head', function () {
        remove_action('wp_head','wp_print_styles',8);  
        remove_action('wp_head','wp_print_head_scripts',9); 
        
        if(621 != $post->ID){
            wp_deregister_style('contact-form-7');
            wp_deregister_script('contact-form-7');
        }
        
        wp_deregister_style('rate-my-post');
        wp_deregister_style('twentyfifteen-style');
        wp_deregister_style('twentyfifteen-fonts');
    },1);

аналогично поступаю с прочими файлами. Также первыми 2-мя строками, перенесу подключение активов в подвал сайта.

Ну что – проверим результат?..

Общая оценка после первой итерации оптимизации
Общая оценка после первой итерации оптимизации
Оставшиеся проблемы по оптимизации
Оставшиеся проблемы по оптимизации

Результаты от сих действий ощутимы(меня они даже поразили!). Но не буду на этом останавливаться, продолжу развлечение…

Изврат с картинками

На деле здесь все просто – никакого извращения нет. По поводу современных форматов изображения, а именно .webp -дело в том, что не все браузеры его поддерживают. В связи с этим вместо такого тега для изображения

<img src="URL" alt="альтернативный текст">

для страниц с webp-картинками требуется такая структура

<picture>
   <source srcset="images/name.webp" type="image/webp">
   <img src="images/name.jpg" alt="описание" />
</picture>

при этом браузеру предлагается вначале загрузить webp, если он его не понимает – грузит “старый” формат. С практики скажу данная модификация дает крайне малый прирост, по этому я сделал альтернативный способ – ленивая загрузка изображений. Суть в том, чтоб браузер, загружая страницу, получал ее без картинок; по мере необходимости изображения подгружаются на javascript – этот метод дал мне большой прирост к скорости – я им и воспользовался. Единственная проблема – индексация картинок поисковыми роботами и, соответственно, можно забыть о трафике через изображения – но я решил, что переживу эту утерю… Итак, о самой загрузке – как же я ее сделал? Мой сайт на вордпресс, я поставил плагин Autoptimize… шучу, мне снего всего одна функция нужна, ее добавить одна(4) строчка

	add_filter( 'wp_get_attachment_image_attributes', function ( $attr ) {
		$attr['loading'] = 'lazy';

		return $attr;
	} );
<img src="URL" alt="альтернативный текст">

так выглядит тег картинки без лени

<img src="URL" loading="lazy" alt="альтернативный текст">

а так с ней. Чтобы добавить lazy-loading достаточно прописать атрибут loading=”lazy”. Однако, опять же, не все браузеры ее поддерживают и иногда нужно ее имитировать на js.

Результат

результат после второй итерации
результат после второй итерации

Согласись, не плохо – уже вплотную я приблизился к зеленой зоне(90). Кста, еще я установил плагин WebP Express для нарезки картинок в современном формате. Единственное замечание – для получения профита нужно в настройках выбрать “Replace image URLs”(вместо замены тегов).

Работаем с таблицами стилей

Здесь я буду использовать пока что мало распространенный способ – динамическое подключение. Сперва отключим стили вовсе

remove_action( 'wp_footer', 'wp_print_footer_scripts', 20 );

при этом , также, отпадут скрипты(не беда). Следующим шагом – выведем в подвал скрипт, который после полной загрузки страницы вставит ссылки на таблицы стилей

        <script>
            window.onload = function () {
                var footer = document.querySelector('footer');

                footer.insertAdjacentHTML('beforeend', `<?php wp_print_styles() ?>`);
            }
        </script

window.onload вызывает функцию после загрузки и отрисовки страницы. На медленных машинах(или с медленным интернет-соединением) при этои будет посойное наложение стилей.

Оптимизируем скрипты

Результат, полученный мною, неплох – но недостаточен. Следующий шаг оптимизация скриптов. Первое, что я хочу сделать – подключать их асинхронно, т.е. параллельно прочим процессам. Чтоб это сделать нужно просто дописать атрибут async к тегу script

<script async="async" src='URL'></script>

вот как это выглядит в разметке, а вот как можно это сделать в коде для вордпресс

add_filter( 'script_loader_tag', function($tag, $handle){
    return str_replace( ' src', ' async="async" src', $tag );
}, 10, 2 );

От единого этого действия мои показатели улучшились(я считаю значительно)

результат после второй * итерации

но на этом со скриптами еще не все.

Далее, я пойду таким же путем, как и со стилями. Тут тоже такое работает, однако реализация отлична. Дело в том, что закрывающийся скрипт-тег в строке, закрывает скрипт(по крайней мере в многострочной строке). В связи с этим, я записал пути в массив и, создавая тег, вставлял ссылки на скрипты

// заполнение переменной to_do 
$wp_scripts->all_deps( $wp_scripts->queue );

foreach ( $wp_scripts->to_do as $handle )://echo $handle.'-'.$wp_scripts->registered[ $handle ]->src.'<br>';
	if ( ! empty( $wp_scripts->registered[ $handle ]->src ) ) {
		$scripts[] = $wp_scripts->registered[ $handle ]->src;
	}
        // вывод зависимого кода
	if ( $wp_scripts->registered[ $handle ]->extra ) {
		echo "n<script>n";
		echo "/* <![CDATA[ */n"; // Not needed in HTML 5.
		echo $wp_scripts->registered[ $handle ]->extra['data'];
		echo "/* ]]> */n";
		echo "</script>n";
	}

endforeach;

конвертирую все это в js

                var scripts = '<?php echo json_encode( $scripts )?>',
                    footer = document.querySelector('footer');

                JSON.parse(scripts).forEach(function (src) {
                    script = document.createElement('script'),
                        script.src = src;
                    script.async = false;

                    footer.append(script);
                })

Все скрипты, кроме ace.js, нормально работают. Немного просмотревуказанный скрипт понял, что проблема с его инициализацией. немного переделав его и подключив его напрямую(в смысле без динамического тега), и он тоже заработал. Результат страницы составил

результат после третей итерации
результат после второй итерации

Не идеально, но все же! Можно еще минификацию активов сделать, но они итак минифицированы. Ну, да и ладно…