Google Chrome будет агрессивно бороться с медленными скриптами на страницах сайтов

Каждый, у кого был медленный интернет, мог наблюдать, как загрузка сайта прерывается на середине, чтобы прогрузить какой-нибудь очень тяжёлый блок. Часто это происходит из-за неправильного встраивания элементов с помощью JavaScript. На эту проблему обратили внимание разработчики Google Chrome, и решать этот вопрос они намерены достаточно радикально.

В чём дело?

В скорости загрузки страниц и особенностях работы браузеров. Прежде чем браузер сможет отобразить страницу, он должен полностью её проанализировать и составить DOM-дерево. Если обработчик встречает в коде скрипт, он вынужден ждать, пока тот закончит свою работу, чтобы продолжить анализ HTML-разметки. Нетрудно догадаться, что когда один скрипт встраивает на страницу другой скрипт, это вызывает цепную реакцию — браузер вынужден ждать, пока следующий скрипт скачается и выполнит свою работу (которая может заключаться в том, чтобы вставить на страницу ещё несколько скриптов, и так далее). Вредной для производительности считаются конструкции подобные следующей:

document.write('<script src="https://paul.kinlan.me/ad-inject.js"></script>');

Это настолько серьёзно?

Если верить исследованиям Google — да. Согласно их данным, для пользователей с медленным соединением (например, 2G) встраивание сторонних скриптов на страницу (а чаще всего через document.write вставляются именно сторонние скрипты) может стоить десятков лишних секунд загрузки. При этом чаще всего этих десятков секунд не проходит — загрузка либо обрывается по техническим причинам, либо пользователю просто надоедает ждать.

Да ладно, с 2G любая загрузка будет длиться десятки секунд

Да, однако блокировка встраиваемых скриптов может существенно улучшить ситуацию. В Google приводят следующую статистику об устройствах с 2G, для которых такая блокировка была выполнена:

  • На 10% больше загрузок стали достигать “first contentful paint” — визуального подтверждения того, что страница действительно загружается;
  • На 25% больше загрузок стали доходить до полного отображения содержимого сайта;
  • Перезагрузок страниц стало на 10% меньше, что может свидетельствовать о большем удовлетворении пользователей результатами от загрузки страницы;
  • На 21% (в среднем — более, чем на секунду) сократилось время загрузки до “first contentful paint”;
  • На 38% сократилось время обработки страницы (в среднем это примерно 6 секунд), что, вероятно, является самым важным показателем для пользователя.

Разве такое встраивание скриптов встречается часто?

По данным Google, такое встраивание встречается в 7,6% от всех загрузок через 2G.

И как с этим будут бороться?

Блокировкой скриптов, встроенных через document.write. Однако это будет выполняться далеко не всегда, а лишь при одновременном выполнении всех следующих условий:

  • У пользователя обнаружена низкая скорость соединения, и он использует 2G (в дальнейшем это условие должно быть расширено для Wi-Fi и 3G соединений, которые не могут обеспечить высокую скорость);
  • Вызов document.write() происходит из основного документа. К примеру, такие вызовы внутри iframe блокироваться не будут (потому что они обрабатываются отдельно и не мешают загрузке основной страницы);
  • Скрипт, вызываемый через document.write, действительно мешает загрузке страницы. Скрипты с атрибутами async и defer блокированы не будут;
  • Вызываемый скрипт не закеширован браузером. Если скрипт уже есть в кеше, то он не будет сильно влиять на скорость загрузки страницы;
  • Обращение к странице не является перезагрузкой. Если пользователь повторно загружает страницу, все скрипты будут обрабатываться как и должны.

Но мне очень нужно, чтобы все мои скрипты загрузились. Что делать?

Самый очевидный ответ — не использовать для их загрузки document.write. У Google есть список сервисов, которые предоставляют скрипты с возможностью асинхронной загрузки, и они очень просят сообщить им, если вы знаете сервис, который должен быть в этом списке, но не попал туда по какой-то причине. Если же вам необходимо использовать сторонние скрипты, которые предоставляются вам с использованием document.write, то вы можете самостоятельно изменить их, добавив атрибут async к элементу script, либо заменить document.write на document.appendChild() или parentNode.insertBefore(), как это делается для Google Analytics.

Как понять, что это может меня затронуть?

Во-первых, стоит узнать, сколько посетителей вашего сайта используют 2G. Это можно сделать с помощью Network Information API:

if(navigator.connection &&
   navigator.connection.type === 'cellular' &&
   navigator.connection.downlinkMax <= 0.115)
  // Notify your service to indicate that you might be affected by this restriction.
}

Во-вторых, при обнаружении встраивания скрипта с помощью document.write в консоли разработчика Google Chrome будет появляться примерно следующее сообщение:

document-write-warning

В-третьих, если скрипт заблокирован, Google Chrome будет отсылать ему заголовок следующего вида:

Intervention: <https://shorturl/relevant/spec>;

В случае риска быть заблокированным, возможно, что Chrome отправит такой и такой заголовок:

Intervention: <https://shorturl/relevant/spec>; level=”warning”

Дополнительную информацию можно почерпнуть в оригинальной заметке на Google Developers.