Pull to refresh

Учим wordpress (и не только) отрисовывать быстро Youtube плееры

Reading time4 min
Views6.4K
youtube-speedload

Я вспомнил сайт одного старого приятеля-программиста, у которого в ленте сайта один хип-хоп, лет 6 назад он плевался на скорость загрузки страниц: «да-да-да, надо переделать, да ничего сложного там нет...» а вот зашел сейчас — все по-старому :-) Не смотря на простые технические решения, допускаю, что не только у меня есть такой приятель. Поэтому эта маленькая техническая заметка.

Чтобы понимать, о какой проблеме мы говорим:
image

400kb скрипта base.js?

Остальное даже не смотрю.
После оптимизации даже без сжатия выигрышь будет в десяки раз и составит:

html — 0.5 kb
css — 1.4 kb
js — 0.2 kb

Мне же и самому приходилось часто публиковать лекции с нашего YouTube канала в ленте сайта, их накаливалось на одной страничке достаточно много. Да и при просмотре личных блогов встречаются подборки чужих или своих видео. И что меня нервировало, то как youtube кладет на производительность при встраивании. Чего там только не грузится через iframe ради той же картинки с кликом. И самое забавное, я просто может и не хочу смотреть видео, нафига мне грузить контент?

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

Вот тот же хабр, у него не так много попадается в ленте видео, поэтому это не столь востребовано. Однако, если популяризировать этот подход?

Давайте попробуем реализовать это на примере плагина для WordPress.

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

Что можно вытащить из Youtube


Youtube для встраивания контента использует oembed. Подробнее мой ответ на SO о том, что можно вытащить, без обращения к официальному API.

stackoverflow.com/questions/10066638/get-youtube-information-via-json-for-single-video-not-feed-in-javascript/23253789#23253789

Ответ в JSON
www.youtube.com/oembed?url=http://www.youtube.com/watch?v=ojCkgU5XGdg&format=json

Или xml
www.youtube.com/oembed?url=http://www.youtube.com/watch?v=ojCkgU5XGdg&format=xml

Типы превьюшек разных размеров hq, sd, maxres
img.youtube.com/vi/ojCkgU5XGdg/hqdefault.jpg
img.youtube.com/vi/ojCkgU5XGdg/sddefault.jpg
i.ytimg.com/vi/ojCkgU5XGdg/maxresdefault.jpg
img.youtube.com/vi/ojCkgU5XGdg/0.jpg
img.youtube.com/vi/ojCkgU5XGdg/1.jpg
img.youtube.com/vi/ojCkgU5XGdg/2.jpg
img.youtube.com/vi/ojCkgU5XGdg/3.jpg

Аннотации к видео
www.youtube.com/annotations_invideo?cap_hist=1&video_id=ojCkgU5XGdg

Еще одна ссылка
www.youtube.com/get_video_info?html5=1&video_id=ojCkgU5XGdg

А это вам пригодится, если вы делаете стримы.
www.youtube.com/embed/live_stream?channel=UCkA21M22vGK9GtAvq3DvSlA

Превью прямых трансляций
i.ytimg.com/vi/W-fSCPrYSL8/hqdefault_live.jpg

Жаль, что YT не поддерживает jsonp. Поэтому полностью отказаться от сохранения данных у нас не получится.

Как вордпресс кеширует oembed


WordPress поддерживает автовстраивание при нахождении ссылок в редакторе из белого списка. При срабатывании этого события он создает мета-поле к посту с префиксом _oembed_, а при выводе — подменяет на html код из кеша.

Если мы решили показывать верстку с подстановкой iframe по клику, то нам необходимо где-то хранить это состояние, лучше всего в том же кеше.

Фильтр add_filter('embed_oembed_html'); позволяет до вывода поста подменить кеш. Он представляет из себя всем известный iframe.

<iframe width="" height=""  src=""></iframe>


Так как пока разбираются, почему гугл не формирует title для своих iframe (ticket #4024) мы, увы, вынуждены делать разово запрос на сервер для захвата title в кеш.

Как обновить кеш своими данными


add_filter('embed_oembed_html', 'ytsl_oembed_html', 1, 3);
ytsl_oembed_html($cache, $url, $attr){};


В момент срабатывания фильтра, я ищу в переменной $cache наличие моего тега data-ytsl. Если его нет, то делаю запрос на

http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=ojCkgU5XGdg&format=json


и формирую содержание нового тега. В итоге кеш выглядит вот так:

<iframe width="" height=""  src=" " data-ytsl=" "></iframe>


Обновление кеша делается так. Сначала считаем ключ
$cachekey   = '_oembed_' . md5( $url . serialize( $attr ) );

А потом обновляем.
update_post_meta( get_the_ID(), $cachekey, $cache );


Если же мой тег data-ytsl обнаруживается, я вытаскиваю из него title и id и формирую html.
В data-iframe я вставляю уже чистый код кеша без моего тега, для того чтобы по клику подменить этим содержанием верстку.

<div class='ytsl-click_div' data-iframe='$ytsl' style='$fixed position:relative;background: url($thumb_url) no-repeat scroll center center / cover' >
    <div class='ytsl-title_grad'>
        <div class='ytsl-title_text'>{$json['title']}</div>
    </div>
    <div class='ytsl-play_b'></div>
</div>"

Css -ка на гитхабе, тут нет смыла ее показывать.

В итоге плеер выглядит вот так.


В качестве отличия, я сделал кнопку play другого цвета. А вот то что тайтл написал Arial, а не кастомным шрифтом, который тоже грузится через iframe, по-моему, ни сколько не влияет на узнаваемость.

Итоговое решение обработки «на лету» очень скоростное, и судя по плагину профайлеру P3 от goDaddy обходится совершенно безболезненно. Поэтому удалось найти баланс между удобством и скоростью. Плагин вообще не требует от пользователя никаких действий. Он просто показывает картинки вместо iframe когда включен.

На фронтенде.

Всего лишь подключаем скрипт. Все до безобразия элементарно:

(function(){
  var f = document.querySelectorAll(".ytsl-click_div");
  for (var i = 0; i < f.length; ++i) {
       f[i].onclick = function () {
	 this.parentElement.innerHTML = this.getAttribute("data-iframe");
      }
    }
})();


Минусы — на мобильных устройствах браузеры шибко умные, и умеют делать это самостоятельно. Поэтому если не делать определение мобильных устройств, для воспроизведения придется делать по два клика.

Итого:
html — 0.5 kb
css — 1.4 kb
js — 0.2 kb
font — 0 kb
img — 50 kb (зависит от фоновой картинки)

Остальных минусов не заметил за довольно большой промежуток времени.

Ну а кота нарисовал в нагрузку за не столь длинный, и не столь технически интересный рассказ.

Код лежит тут github.com/Alexufo/youtube-speedload
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 12: ↑10 and ↓2+8
Comments10

Articles