В 2011 году компанией Google был представлен бесплатный сервис рекомендаций разработчикам веб-страниц по ускорению отображения страницы в браузере клиента. Принцип работы сервиса:
Ниже на простом примере будет показан визуальный эффект от одной идеи, рекомендуемой сервисом PageSpeed Insights:
Мы попробуем перенести в самый её конец, то есть максимально отложить стилизацию / запуск скриптов. Такое перемещение изменит порядок действий браузера так, что парсинг разметки начнётся до подкачки вторичных файлов, как следствие клиенту можем немедленно показать те подробности, которые он терпит увидеть на короткое время даже нестилизованными, лишь бы скорее получить реакцию сайта. Таковыми могут оказаться и вводный текст, и основная картинка предмета публикации, и что-нибудь ещё, служащее цели уже сейчас начать удовлетворять интерес клиента, пока страница догружается. Даже банальный индикатор «загружается», на котором и построим пример.
Цель же примера — показать зрительную разницу между обработкой одного и другого устройства страницы.
А зачем?
Раньше проектирование страниц сайта покоилось вне вопросов оптимизации, которая заботилась лишь быстрым извлечением данных, размещением их на странице и отправке клиенту. Со временем выяснилось, что устройство страницы, а именно компоновка и подключаемые дополнения, ощутимо влияет на другой аспект скорости, до того не замечавшийся, — как скоро клиент увидит результат на экране браузера.
Ведь быстро обработав запрос клиента и послав ответ, мы рассчитываем на положительную эмоцию от скорости сайта. Клиент же видит события иначе:
На самом деле, когда клиент видит белый экран и далее ожидает, документальная часть ответной страницы как правило уже принята, но в связи с её стандартным строением, браузер вынужден отложить прорисовку, пока не подкачает файлы скриптов и стилей, объявленные в заголовках страницы.
Как раз здесь можно принять упоминавшуюся меру и тем самым разблокировать прорисовку.
Стоит ли овчинка выделки?
Некоторые владельцы сайтов ошибочно понимают сервис PageSpeed Insights как консультанта по ускорению работы сайта. Одновременно воображая, что достижение высоких процентов в нём каким-то образом повлияет на ранжируемость страниц.
На самом же деле сервис озадачен сокращением времени между кликом по ссылке и началом демонстрации каких-то элементов страницы. Это не влияет на ранжируемость, так как затрагивает лишь визуальную составляющую процесса загрузки, но благотворно влияет на пользователя, поскольку он видит живой отклик, притом что сайт в сущности продолжает работать с прежней скоростью.
Однако следует понимать, если ваш интерфейс или дизайн страниц не предназначен к демонстрации без полного набора стилей и скриптов, пользоваться рекомендациями сервиса нужно осторожно, иначе сайт покажется быстрым, но кривоватым, ведь на короткий миг посетитель будет видеть сбившиеся в кучу нестилизованные фрагменты страницы, которые затем резко приходят в нормальный вид. Впрочем, это актуально только на первом запросе, далее в дело вступает кеш стилей, благодаря ему короткий миг сжимается в незаметное мгновение.
Теперь перейдем к сравнению. Начнём со стандартного устройства страницы.
Страницы на тормозах внешних CSS и JS
Согласно спецификации языка гипертекстовой разметки (HTML4, HTML5), веб-документ должен содержать секции <head>, <body> именно в таком порядке и ничего более. Причём секции должны обрабатываться браузером одна за другой, а объявления скриптов и стилей предложено размещать в секции <head> из соображений отделить правила внешнего вида, управляющую логику и разметку страницы.
В результате, если в заголовочной части объявлены внешние подключения, пока они не будут получены все, нельзя перейти к обработке секции разметки, то есть её парсингу и дальнейшей прорисовке.
Логичен вопрос: почему же нельзя обработать секции параллельно? К моменту парсинга формально существует пустая DOM (объектная модель документа), которая в дальнейшем наполнится на основе парсинга. Однако поскольку в заголовочной секции допустимо подключение скриптов, а те в свою очередь могут задействовать например методы writeln, write объектной модели, то если параллельно идёт парсинг и DOM наполняется с какой-то скоростью, зависящей от производительности компьютера, тогда методы запишут свои изменения DOM в её непредсказуемой точке. Чтобы избежать конфликта, секции обрабатываются только одна за другой.
Чтобы вы убедились, что именно так всё и происходит в браузере, испытаем пример на основе следующей разметки: в <head> объявлен внешний стиль style.css и некий скрипт script.js, в <body> — индикатор загрузки и некий настоящий контент, изначально невидимый.
Казалось бы, не учитывая особенности спецификации HTML, а именно что браузер не перейдёт к секции <body> пока не закончит обработку <head>, мы ожидали бы, что страница появится на экране так:
Однако посмотрите живое демо этого примера: imperacms.ru/tests/page-loading/css-js-body.php. Белый экран вместо ожидаемого индикатора, пока выполняется загрузка. То есть в момент, когда пошла загрузка стилей и скриптов, которая при разных условиях соединения может потребовать немало времени, уже можно было показать на экране либо какой-то текст страницы, или хотя бы украшательство в виде индикатора загрузки. Нечто типа такого:

Но смотрите, что происходит в реальности. Индикатор не успевает быть показан, потому что прорисовка отложена необходимостью полной обработки секции <head>. В то время как в последнем примере ниже, где страница устроена иначе, индикатор показывается в нужное время, а именно сразу после того, как произошла загрузка html, а после загрузки всех подключаемых элементов страницы автоматически исчезает и на экране появляется основной контент.

Заметка Кроме показанной выше испытательной разметки, в демо добавлен простой технический скрипт, который выводит на экран красным цветом строки этапов загрузки страницы. На скоростных интернет-соединениях, где прокачка быстрая и задержки отрисовки небольшие, так удобно видеть, что и в какой последовательности обрабатывалось.
Ещё лучше смотрится то же самое демо, но с пошаговой паузой после каждого этапа: imperacms.ru/tests/page-loading/css-js-body.php?paused. Хорошо видно, что же на самом деле показывает браузер в каждый момент этой «растянутой» во времени загрузки.
Страницы с внешними CSS и JS без тормозов
Теперь рассмотрим нестандартное устройство страницы. Последуем рекомендации PageSpeed Insights, перенесём все подключения в секцию <body>. И загрузка страницы станет выглядеть правильно, как мы ожидали вначале.
Живое демо: imperacms.ru/tests/page-loading/index.php.
То же демо с пошаговой паузой: imperacms.ru/tests/page-loading/index.php?paused.
Здесь уже схема прорисовки страницы выглядит так:
То есть при подобном подходе в принципе есть возможность анимировать проявление страницы по частям, по мере того, как подгрузятся разные фрагменты стилей, предварительно разделённые на самодостаточные css-файлы, отвечающие за внешний вид конкретных элементов.
- анализ содержимого предложенной ссылки,
- перечисление элементов страницы, приводящих к замедлению её прорисовки:
- либо в силу неэффективной цепи вторичных запросов к сайту, подкачивающих сопутствующие файлы страницы,
- либо в силу наличия неуплотнённых данных в этих файлах,
- и подсказка способа оптимизации в каждом случае.
Ниже на простом примере будет показан визуальный эффект от одной идеи, рекомендуемой сервисом PageSpeed Insights:
- если на вашей странице есть подключаемые стили и скрипты, перенесите подключения из заголовочной части документа в разметочную.
Мы попробуем перенести в самый её конец, то есть максимально отложить стилизацию / запуск скриптов. Такое перемещение изменит порядок действий браузера так, что парсинг разметки начнётся до подкачки вторичных файлов, как следствие клиенту можем немедленно показать те подробности, которые он терпит увидеть на короткое время даже нестилизованными, лишь бы скорее получить реакцию сайта. Таковыми могут оказаться и вводный текст, и основная картинка предмета публикации, и что-нибудь ещё, служащее цели уже сейчас начать удовлетворять интерес клиента, пока страница догружается. Даже банальный индикатор «загружается», на котором и построим пример.
Цель же примера — показать зрительную разницу между обработкой одного и другого устройства страницы.
А зачем?
Раньше проектирование страниц сайта покоилось вне вопросов оптимизации, которая заботилась лишь быстрым извлечением данных, размещением их на странице и отправке клиенту. Со временем выяснилось, что устройство страницы, а именно компоновка и подключаемые дополнения, ощутимо влияет на другой аспект скорости, до того не замечавшийся, — как скоро клиент увидит результат на экране браузера.
Ведь быстро обработав запрос клиента и послав ответ, мы рассчитываем на положительную эмоцию от скорости сайта. Клиент же видит события иначе:
- посылаю запрос,
- вижу белый экран,
- ожидаю (что-то грузится),
- страница открылась.
На самом деле, когда клиент видит белый экран и далее ожидает, документальная часть ответной страницы как правило уже принята, но в связи с её стандартным строением, браузер вынужден отложить прорисовку, пока не подкачает файлы скриптов и стилей, объявленные в заголовках страницы.
Как раз здесь можно принять упоминавшуюся меру и тем самым разблокировать прорисовку.
Стоит ли овчинка выделки?
Некоторые владельцы сайтов ошибочно понимают сервис PageSpeed Insights как консультанта по ускорению работы сайта. Одновременно воображая, что достижение высоких процентов в нём каким-то образом повлияет на ранжируемость страниц.
На самом же деле сервис озадачен сокращением времени между кликом по ссылке и началом демонстрации каких-то элементов страницы. Это не влияет на ранжируемость, так как затрагивает лишь визуальную составляющую процесса загрузки, но благотворно влияет на пользователя, поскольку он видит живой отклик, притом что сайт в сущности продолжает работать с прежней скоростью.
Однако следует понимать, если ваш интерфейс или дизайн страниц не предназначен к демонстрации без полного набора стилей и скриптов, пользоваться рекомендациями сервиса нужно осторожно, иначе сайт покажется быстрым, но кривоватым, ведь на короткий миг посетитель будет видеть сбившиеся в кучу нестилизованные фрагменты страницы, которые затем резко приходят в нормальный вид. Впрочем, это актуально только на первом запросе, далее в дело вступает кеш стилей, благодаря ему короткий миг сжимается в незаметное мгновение.
Теперь перейдем к сравнению. Начнём со стандартного устройства страницы.
Страницы на тормозах внешних CSS и JS
Согласно спецификации языка гипертекстовой разметки (HTML4, HTML5), веб-документ должен содержать секции <head>, <body> именно в таком порядке и ничего более. Причём секции должны обрабатываться браузером одна за другой, а объявления скриптов и стилей предложено размещать в секции <head> из соображений отделить правила внешнего вида, управляющую логику и разметку страницы.
В результате, если в заголовочной части объявлены внешние подключения, пока они не будут получены все, нельзя перейти к обработке секции разметки, то есть её парсингу и дальнейшей прорисовке.
Логичен вопрос: почему же нельзя обработать секции параллельно? К моменту парсинга формально существует пустая DOM (объектная модель документа), которая в дальнейшем наполнится на основе парсинга. Однако поскольку в заголовочной секции допустимо подключение скриптов, а те в свою очередь могут задействовать например методы writeln, write объектной модели, то если параллельно идёт парсинг и DOM наполняется с какой-то скоростью, зависящей от производительности компьютера, тогда методы запишут свои изменения DOM в её непредсказуемой точке. Чтобы избежать конфликта, секции обрабатываются только одна за другой.
Чтобы вы убедились, что именно так всё и происходит в браузере, испытаем пример на основе следующей разметки: в <head> объявлен внешний стиль style.css и некий скрипт script.js, в <body> — индикатор загрузки и некий настоящий контент, изначально невидимый.
<html>
<head>
<title> Тест БЕЛЫЙ ЭКРАН пока страница не подгрузится целиком</title>
<link href="style.css" rel="stylesheet" type="text/css" />
<script src="script.js" type="text/javascript"></script>
</head>
<body>
<center id="progress"> здесь индикатор загрузки </center>
<div id="body" style="display: none;">
здесь реальный контент страницы
</div>
</body>
</html>
Казалось бы, не учитывая особенности спецификации HTML, а именно что браузер не перейдёт к секции <body> пока не закончит обработку <head>, мы ожидали бы, что страница появится на экране так:
- сначала индикатор загрузки id=«progress»,
- а когда подкачаются стиль и скрипт, они скроют индикатор и проявят контейнер-обёртку id=«body».
Однако посмотрите живое демо этого примера: imperacms.ru/tests/page-loading/css-js-body.php. Белый экран вместо ожидаемого индикатора, пока выполняется загрузка. То есть в момент, когда пошла загрузка стилей и скриптов, которая при разных условиях соединения может потребовать немало времени, уже можно было показать на экране либо какой-то текст страницы, или хотя бы украшательство в виде индикатора загрузки. Нечто типа такого:

Но смотрите, что происходит в реальности. Индикатор не успевает быть показан, потому что прорисовка отложена необходимостью полной обработки секции <head>. В то время как в последнем примере ниже, где страница устроена иначе, индикатор показывается в нужное время, а именно сразу после того, как произошла загрузка html, а после загрузки всех подключаемых элементов страницы автоматически исчезает и на экране появляется основной контент.

Заметка Кроме показанной выше испытательной разметки, в демо добавлен простой технический скрипт, который выводит на экран красным цветом строки этапов загрузки страницы. На скоростных интернет-соединениях, где прокачка быстрая и задержки отрисовки небольшие, так удобно видеть, что и в какой последовательности обрабатывалось.
Ещё лучше смотрится то же самое демо, но с пошаговой паузой после каждого этапа: imperacms.ru/tests/page-loading/css-js-body.php?paused. Хорошо видно, что же на самом деле показывает браузер в каждый момент этой «растянутой» во времени загрузки.
Страницы с внешними CSS и JS без тормозов
Теперь рассмотрим нестандартное устройство страницы. Последуем рекомендации PageSpeed Insights, перенесём все подключения в секцию <body>. И загрузка страницы станет выглядеть правильно, как мы ожидали вначале.
<html>
<head>
<title> Тест ИНДИКАТОР ЗАГРУЗКИ пока страница грузится </title>
</head>
<body>
<center id="progress"> здесь индикатор загрузки </center>
<div id="body" style="display: none;">
здесь реальный контент страницы
</div>
<script src="script.js" type="text/javascript"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
</body>
</html>
Живое демо: imperacms.ru/tests/page-loading/index.php.
То же демо с пошаговой паузой: imperacms.ru/tests/page-loading/index.php?paused.
Здесь уже схема прорисовки страницы выглядит так:
- загружается html,
- на экране появляется индикатор загрузки,
- в этот момент начинается подгрузка скриптов, стилей,
- с окончанием загрузки индикатор исчезает, появляется страница целиком.
То есть при подобном подходе в принципе есть возможность анимировать проявление страницы по частям, по мере того, как подгрузятся разные фрагменты стилей, предварительно разделённые на самодостаточные css-файлы, отвечающие за внешний вид конкретных элементов.