Улучшение субъективной скорости работы сайта при помощи подсказок браузеру

в 17:28, , рубрики: prerender, Блог компании Surfingbird, оптимизация, разработка, метки: ,

Я удивлен, что эта техника упоминалась на Хабре только один раз и вскользь — если верить поиску, конечно.
Меня не покидает ощущение, что на самом деле все про это знают, но я всё же расскажу.

Суть в том, что браузеру можно подсказать, какую страницу пользователь откроет следующей — и он начнет её загружать заранее.

Делается это несложно — нужно всего-то добавить пару мета-тегов в head:

<link rel="prefetch" href="NEXT PAGE URI" />
<link rel="prerender" href="NEXT PAGE URI" />

Теперь подробнее про ограничения и нюансы.

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

Во-вторых, поддерживают такие финты ушами на данный момент AFAIK только Firefox и Chrome, причем первый — уже много лет, что любопытно. Собственно, первое значение rel распознает Firefox, второе — Chrome. Между ними есть разница, и заключается она в том, что в Chrome это реализовано намного лучше, подробнее чуть позже.

Но вариант с prefetch есть в текущей редакции WHATWG: www.whatwg.org/specs/web-apps/current-work/#link-type-prefetch. Это не значит, что WHATWG выбрали худший из двух вариант — определение значения этого атрибута весьма обобщено («браузеру следует закешировать указанный контент»), и ничто не мешает конкретному браузеру заставить это работать на уровне Chrome или даже лучше.

Так что можно надеяться, что и в других браузерах поддержка появится, особенно на движке WebKit (надо понимать, в Gecko-based браузерах это уже есть, но где они, популярные Gecko-браузеры, кроме FF?)

В-третьих, важно понимать, что браузер начинает что-то подгружать только после того, как загрузил текущую страницу целиком — причем в FF учитывается и скачивание файлов браузером, и, вероятно, какая-то сетевая активность в других табах, et cetera.
Впрочем, полагаю, Chrome может традиционно быть более агрессивен в этом вопросе и начинать грузить на более раннем этапе — но я свечку не держал. Если кто-то может посмотреть прямо в сорцах — будет интересно узнать точно.

Закончим на мажорной ноте — в обоих браузерах эти мета-теги абсолютно корректно работают и при динамическом добавлении. А ещё их может быть несколько.

Теперь, в чем, собственно, разница между prefetch в Firefox и prerender в Chrome?
Chrome, встречая инструкцию prerender, создает невидимый таб, и начинает загружать в нем страницу, со всеми скриптами (которые он даже исполняет), картинками, и так далее. Если пользователь действительно переходит по предсказанному адресу, текущий таб заменяется на этот невидимый, и он оказывается на уже загруженной — или как минимум загружающейся — странице.
Firefox же всего лишь загружает html указанной страницы, все внешние ресурсы начинают загружаться только при переходе. Я не нашел этого в официальном FAQ на MDN [1], и даже не нашел, где я это изначально прочитал — но полевые эксперименты с 15-й версией вроде бы говорят, что так всё и есть.

Правда, тут надо оговориться — указывать в мета-теге можно не только адреса страниц, но и ссылки на css, картинки, you name it. Так что можно созданием новых тегов заставить FF загрузить и побольше — но это далеко от элегантности.
Впрочем, в подходе Chrome тоже можно найти минусы, особенно если вспомнить, что не у всех безлимит — но мне он симпатичнее.
Видимо, потому что у меня безлимит есть :)


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

Так вот начали мы с того, что начали запрашивать следующую рекомендацию не когда он нажал на кнопку «Серф» — которая, собственно, суть этакое «Дальше!» — а прямо сразу, по document ready, и уже на этом стали экономить миллисекунд так по 300.
А поскольку в ответе возвращается и полный url следующей страницы, мы начали на лету генерировать эти мета-теги с полученным url — и экономить ещё больше.

Остается последний нюанс — пользователь при серфинге может задавать настройки — вроде ограничения категорий, доменов, авторов ссылок — и важно, конечно, использовать заранее полученные рекомендации только если настройки не поменялись. Однако это соблюдается в подавляющем большинстве случаев.

Визуально в Chrome получается, что если на несколько секунд задержаться на текущей странице, следующая открывается мгновенно. Эффект потрясающий — радовались как дети, когда проверяли :)


Убедиться в том, что ОНО работает, в Chrome можно тут — chrome://net-internals/#prerender, про FF не подскажу, к сожалению.

Я предвижу замечания, что это влияет на статистику и даже, может быть, нарушает privacy (не в случае сайта surfingbird.ru, конечно, а в общем — представьте, что злые люди сказали вашему браузеру загрузить страницу с детским порно и ваш ip попал в логи), увеличивает трафик, и ещё что-нибудь.
С одной стороны, на часть вопросов можно ответить, что FF при префетчинге посылает специальный заголовок, а Chrome предлагает использовать Page Visibility API, а с другой — я лично не считаю это серьезными проблемами. Преимущества мне кажутся намного более весомыми.

[1] developer.mozilla.org/en-US/docs/Link_prefetching_FAQ
[2] www.chromium.org/developers/design-documents/prerender

Автор: Skaurus

Поделиться

* - обязательные к заполнению поля