Компания
97,55
рейтинг
10 сентября 2012 в 21:28

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

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

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

Делается это несложно — нужно всего-то добавить пару мета-тегов в 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 учитывается и скачивание файлов браузером, и, вероятно, сетевая активность в других табах.
Впрочем, полагаю, 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
Surfingbird
рейтинг 97,55

Комментарии (44)

  • +2
    Интересно, спасибо :) relationship вообще хорошая вещь, даже без подгрузки (пользуюсь поддерживаемыми Оперой «prev», «next» и т.д., а теперь будет ещё над чем поэкспериментировать.

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

    Да, privacy нарушается и очень сильно, но, имхо, это должна быть проблема разработчиков самих браузеров, а не тех, кто использует функционал rel'ов

    • +8
      Если так судить, то iframe тогда вообще дыра, да и js не лучше.
    • 0
      Ура, пожалуйста :)

      Кстати, насчет privacy — и в FF, и в Chrome предзагрузку можно отключить — about:config, network.prefetch-next в FF, «Предсказывать сетевые действия для ускорения загрузки страниц» в Chrome.
  • +3
    Чтобы не учитывать в статистике prerender (и выключить в нём AJAX и видео, так как иначе prerender не будет работать) можно использовать Visibility.js. С помощью Page Visibility API можно узнать, что страница ещё только пререндериться.
  • +4
    Что насчёт актуальности контента?
    Контент на Хабре обновляется каждые минут 5-15, а на чтение одной страницы может уйти около 5 минут.

    Сейчас, переходя на следующую страницу, я могу увидеть пару постов с прошлой.
    И именно так я понимаю, что появилось что-то новое.

    В случае с prefetch, возможны казусы в акутальности страниц.
    • 0
      Я думаю, автор имел ввиду многостраничный статический контент, вроде постов в блоге, например на thg.
      • +2
        Да, верно. Я привёл пример вероятных недостатков этой методики на очень динамичном контенте.
    • +6
      Имхо пейджинг на Хабре — вообще отдельная тема для разговора.
      • 0
        Good to know.
    • +1
      Chromium согласно ссылке в конце статьи сохраняет загруженную страницу только 30 секунд — что потом, не знаю. Либо загружает заново, что маловероятно, либо просто пререндеринга при открытии не случится.

      Это, кстати, очень интересно было бы выяснить, но, опять же, только сорцы.

      Вообще для случая, скажем, длинных статей получается какая-то ерунда — пока я её читаю, у меня всё выпадет из пререндеринга. Надо поэкспериментировать…
  • 0
    Спасибо, я вот не знал про такой функционал, был приятно удивлён! Будем ждать полноценную поддержку
  • +8
    В свое время rel=«next», rel=«prev» (кажется файрфокс в какой-то из версий стал подгружать страницы внезапно по ним, потом в следующих кажется перестал) некисло вынесли мозг в попытках выяснить
    а) Какого черта на сервер идет 3 запроса, а не 1
    б) Почему вдруг поперла статистика хитов вдруг стала расти
    в) Почему некоторые пользователи только зайдя на сайт сразу жмут другие страницы
    г) Зачем сначала возросла нагрузка, а потом многие стали жаловаться на бан.
    И т.д.
    p.s.: разгадка конечно оказалась простой, да и вообще такие вещи знать бы следовало конечно, но запомнилось надолго…
  • +4
    Про prerender, аналогичный подход я использовал при разработке интерфейса терминалов Qiwi.

    Большая часть пользователей жмёт «Оплата услуг» и я хотел оптимизировать этот момент.
    После нажатия на эту кнопку, просто сдвигается iframe с предзагруженой страницей групп провайдеров.
    Выходит моментально и чувствуется «быстрый старт».
    • 0
      Круто.

      У меня, кстати, для серфинга тоже была идея использовать два ифрейма — один показывается, второй грузит следующую страницу, потом они меняются местами.
      Но так, как в этой статье, оказалось намного проще сделать. Зато с ифреймами работало бы везде… и глючило тоже везде)
      • 0
        На терминалах движок Trident и, на фоне ярой борьбы с утечками, мечтать о Nu'school не приходилось :-)
        • 0
          :) А вот, кстати, почему железки тяготеют к ванильному IE? Ведь что угодно можно поставить.
          • 0
            Эти причины мне не понятны.
            Подозреваю, что жёсткая экономия жёсткого диска.
            • 0
              Отстой.
              • 0
                Бизнес, да.
  • +3
    Убедиться в том, что ОНО работает, в Chrome можно тут — chrome://net-internals/#prerender

    Сколько же всякого… лишнего грузит браузер просто так.
  • +1
    Во-вторых, поддерживают такие финты ушами на данный момент AFAIK только Firefox и Chrome

    А мне казалось, что это было в Опере с чёрте помнит какой версии. Или, может, это делалось иначе, но панель навигации с кнопками перехода на следующую и предыдущую страницу она имела.
    • 0
      Хотя, конечно, вряд ли она их умела заранее рендерить.
      • +1
        Функция «Fast Forward» (в русском переводе — Быстрый переход) появилась в 2002 году в Opera 7. Есть она и сейчас, только кнопка убрана из интерфейса (есть в настройках — можно вернуть самостоятельно). Принцип работы простой: браузер самостоятельно пытается определить, на какую следующую страницу пользователь перейдёт, и при активации данной функции (нажатии на кнопку в интерфейсе или на пробел на клавиатуре) открывает эту страницу. Удобно при чтении многостраничных документов, просмотре фотогалерей в Full Screen и т.д. Также параллельно использовался и способ с rel=«next», rel=«prev», позволяющий организовать последовательное открытие страниц веб-сайта с документацией, к примеру. Сейчас работу этой функции можно проверить в любой версии Opera (после 7, естественно), в справке Opera (но не по 12 версии, а максимум по 11.60 help.opera.com/Windows/11.60/en/ ).

        Пре-рендеринга мы не делали по очень понятной причине: трафик. Opera всегда славилась как экономичный браузер, а в те годы (2002) о безлимитке только мечтали, платили зачастую помегабайтно и сидели на dial-up. Естественно, предзагрузка (тем более — ненужных страниц) пробивала бы огромную брешь в бюджете на интернет или тормозила бы всю работу в сети.
        • 0
          Судя по Вашему описанию, нет ни пререндеринга, ни префетчинга.

          Я так и думал, но все же не нашел в документации однозначного доказательства, что страницы не подгружаются. Спасибо за прояснение!
  • 0
    А скажите, уважаемый, фраза «финт ушами» часто ли Вами употребляется? ;) Мне для соц.исследования, если что…
    • 0
      Ого :) Ну, сложно сказать, как часто — но это часть привычного лексикона.
  • 0
    Жаль, но применимо к «статичным» страницам, для которых не передаются POST-ом данные.
    Например в пошаговом мастере, в котором от выбора параметров текущего шага зависит следующий, этот подход не применим.
    • 0
      Ну да, у вас просто не получится в мета-теге указать нужный метод.

      Да и если даже целевая страница сама запустит POST-запрос, Chrome просто отменит пререндеринг, например.

      И это совершенно правильно, IMHO.
  • 0
    Не уловил
    Как собственно «помечать» те ссылки на страницы, которые мы хотим грузить юзеру фоном?
    • 0
      Надо в head-секцию добавить два мета-тега:

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


      Если вам по какой-то причине нужно именно помечать ссылки, то тогда придется написать JS, который будет искать такие ссылки и добавлять те же мета-теги для каждой помеченной.
  • +2
    Решил поделиться тем что получилось у меня.

    Карта кликов пагинатора (яндекс-метрика):



    Код скорее всего не оптимальный, но он работает, писал по-быстрому (Drupal):

    	<?php 
    		if(arg(0)== 'place' && !arg(1)){
    			if(isset($_GET['page'])){
    				$next = $_GET['page']+1;
    				?>
    					<link rel="prefetch" href="http://bestmaps.ru/place?page=<?php echo $next; ?>" />
    					<link rel="prerender" href="http://bestmaps.ru/place?page=<?php echo $next; ?>" />
    				<?php
    			} else {
    				?>
    					<link rel="prefetch" href="http://bestmaps.ru/place?page=1" />
    					<link rel="prerender" href="http://bestmaps.ru/place?page=1" />
    				<?php
    			}
    		}
    	?>
    	
    


    Отмечу, что данная фича по дефолту не работает в хромиуме который стоит у жены (правда давно не обновлялся), и не работает в Irone Chrome, опять-же по дефолту. В хроме конечно эффект фантастический, как раз тот случай, когда можно скзать «WOW-эффект». Автору спасибо за топик, подсыпаю в карму. К слову, Firefox у меня работает не намного медленнее (13 версия)
    • +1
      Вот это научный подход :)

      Iron Chrome вроде заточен на, мм, безопасность/privacy пользователя, так что там сильно прикручена самостоятельность исходного браузера. Вероятно, пререндеринг по умолчанию отключен.
      • 0
        Кстати, в хроме замечена еще такая деталь. Если прогуливаясь по пагинатору остановиться например на пятой странице, и например отойти на 5 минут, или переключить на другую вкладку и забыть, то по возвращении при переходе на следующую страницу (шестую) она будет грузиться долго, как обычно. Видимо это говорит о том, что хром выгружает незадействованные пререндеренные страницы через несколько минут
        • +1
          Ну да, что-то такое описывалось для хромиума.

          Я вот думаю, по уму, браузеру надо бы после истечения этого некоего таймаута слать на закешированную страницу If-Modified-Since или ETag, ну, если заголовкие соответствующие у страницы есть.
          Может быть, он даже так и делает…

          А сбрасывать кеш только если я ушел со страницы, которая выдала подсказку.
    • 0
      Сорри, а куда писать данный код?
      • 0
        я писал в html.tpl.php
        • 0
          в раздел HEAD
  • 0
    Век живи, век учись. Я не знал этого. Спасибо.
  • 0
    Выявил такую странность, что если на страницу с prerender зайти по ссылке с target=_blank, пререндер не будет работать, пишется window.opener, как исправить не знаю.
    • 0
      видимо target=_blank это новая вкладка, а пререндер думает что юзер будет открывать в текущей вкладке
      • 0
        Нет, это логичней было бы если вкладка которая открывается в target=_blank не использовала prerender.
        Но я имею ввиду что мы откудато через target=_blank переходим на страницу, на этой странице указание на prerender, а с нее переходим на указанную на предыдущей странице ссылку, и в таком случае не работает. Както так. :)
  • 0
    Интересная технология.

    У меня возникло пару вопросов уважаемым комментаторам:
    1) Будет ли срабатывать Google Analytics при таком пререндере?
    2) Есть ли легкий способ понять, что у пользователя медленный интернет/мобильный интернет и не включать для него эту функцию?
    3) В интернет-магазине какие могут быть точно угадываемые последовательности? Пейджинг в каталоге, что ещё?
    • +1
      1) Вроде гугл в своей аналитике использует Page Visibility API, а заголовок FF учитывать ещё проще, так что я бы поставил на то, что всё ок.
      2) Тут следует полагаться на интеллект браузера, что он сам не включит пререндер в таком случае, думаю.
    • +2
      3. Я думаю, что пейджинг на странице категорий и возврат в категорию из товара, по хлебным крошкам, к примеру

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка