16 сентября 2013 в 18:33

Mobify.js — изменение DOM до начала загрузки ресурсов

image

Mobyfy.js — открытая библиотека, предназначенная прежде всего для облегчения создания отзывчивых (responsible) сайтов. Основная фишка состоит в так называемом «Capturing API» — позволяющем модифицировать DOM непосредственно ДО начала загрузки браузером ресурсов (скриптов, изображений и т.д.)

Вот пример работы с отзывчивыми изображениями:

<picture>
    <source src="/examples/assets/images/small.jpg">
    <source src="/examples/assets/images/medium.jpg" media="(min-width: 450px)">
    <source src="/examples/assets/images/large.jpg" media="(min-width: 800px)">
    <source src="/examples/assets/images/extralarge.jpg" media="(min-width: 1000px)">
    <img src="/examples/assets/images/small.jpg">
</picture>

Файл «small.jpg» не будет загружен на клиенте с большим экраном, вместо него загрузится то, что будет соответствовать медиа-критерию (можете проверить в веб-инспекторе на закладке «сеть»).

Пример кода, подменяющий все изображения на странице:
Развернуть код
<script id="main-executable" class="mobify">
var main = function () {
    var capturing = window.Mobify && window.Mobify.capturing || false;
    if (capturing) {
        // Grab reference to a newly created document
        Mobify.Capture.init(function(capture){

            var capturedDoc = capture.capturedDoc;

            var grumpyUrl = "/mobifyjs/examples/assets/images/grumpycat.jpg"

            var imgs = capturedDoc.getElementsByTagName("img");
            for(var i = 0; i < imgs.length; i++) {
                var img = imgs[i];
                var ogImage = img.getAttribute("x-src");
                img.setAttribute("x-src", grumpyUrl);
                img.setAttribute("old-src", ogImage);
            }
            
            // Render source DOM to document
            capture.renderCapturedDoc();
        });
    }
}; main();
</script>

Принцип работы довольно интересен: на странице в начало тега HEAD вставляется скрипт, временно оборачивающий содержимое BODY в тег PLAINTEXT — это предотавращает загрузку рессурсов. Далее выполняется наш код, манипуляции с DOM, ну а в конце BODY восстанавливается и ресурсы грузятся.

Поддержка браузерами:
  • Webkit (Safari, Chrome, etc) — все версии
  • Firefox 4.0+
  • Opera 11.0+
  • Internet Explorer 10+

Официальный сайт, интересное обсуждение на сайте мозилы — в комментариях есть разъяснение технологии.
Артур Заяц @zag2art
карма
186,7
рейтинг 0,1
Самое читаемое Разработка

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

  • 0
    реССССССССурсов…
    • 0
      Спасибо, постоянно ошибаюсь :(
  • +5
    А немного оффтоповый вопрос — есть ли смысл в
    var main = function () {
    //...
    }; main();
    

    а не
    (function () {
    //...
    })();
    

    Как минимум не засирается глобальная область видимости.

    И еще — зачем тегу script id и class?

    А по сабжу — довольно интересно, на первый взгляд, надо ковырнуть
    • 0
      зачем тегу script id и class?
      Например, чтобы что-нибудь вставить перед ним в DOM-дерево без необходимости наличия статически присутствующего пустого контейнера (тоже с идентификатором) перед элементом SCRIPT. Способ достичь результата, аналогичного document.write() (динамическая генерация и вставка чего-либо непосредственно в место, где находится элемент SCRIPT), без использования собственно document.write().
  • 0
    А как к этому отнесутся поисковики?)
    • 0
      Нормально отнесутся, они же не будут выполнять скрипт, превращающий body в плейнтекст. След-но, страница для поисковиков останется нетронутой.
      • +1
        Таким обазом, поисковик получит не тот же контент, что получит пользователь. А поисковики этого не любят.
        • 0
          Тот-тот. Вообще зависит от проектирования интерфейса. Изменится незначительно разметка, но контент останется прежним.
          Совсем другая история получается с шаблонизацией на клиенте — там результаты действительно отличаются разительно.
      • +1
        Нынче поисковики и js выполняют
        • 0
          Серьезно? А можно поподробней?
          • +1
            Matt Cutts:

            «For a while, we were scanning within JavaScript, and we were looking for links. Google has gotten smarter about JavaScript and can execute some JavaScript. I wouldn't say that we execute all JavaScript, so there are some conditions in which we don't execute JavaScript. Certainly there are some common, well-known JavaScript things like Google Analytics, which you wouldn't even want to execute because you wouldn't want to try to generate phantom visits from Googlebot into your Google Analytics».
    • 0
      Mobify.js никак не влияет на SEO.

      — Майк из Mobify
  • +1
    Это вы медиавыражение (media query) назвали «медиа-критерием»?
    • +2
      Ага. Немного непривычно? Обычно media query в статьях почему-то на русский не переводят, если переводят — то чаще всего используется калька — медиа-запрос, ну а я немножко отклонился от стандарта, как и вы, по моему :)
  • +6
    <plaintext>
    Этот элемент является нерекомендуемым (deprecated) начиная с HTML 2 и не был реализован ни во всех браузерах, ни взаимно совместимым образом. Более того, в HTML 5 он является устаревшим (obsolete), и соответствующие стандарту браузеры могут вывести его как элемент <pre>, что приведёт к интерпретации содержащегося в нём HTML-кода.
    MDN
    • 0
      Да, все это обсуждается на мозиловском сайте, и, как это не странно, plaintext реализован во всех браузерах, причем сходным образом.
  • 0
    С одной стороны это круто — умный HTML парсер на JavaScript с поддержкой media queries. Но с другой стороны был дублирован тот функционал, что уже есть у бразуера …и к тому же повторили его на JavaScript.

    Выдержка из заметки Bryan McQuade в вольном переводе.
  • +1
    Вот уж воистину сатанизм! Все мы хотим, чтобы сайты начали как можно раньше загружаться, особенно на слабых каналах, пишем всякие аналоги flush(), и вот все коту из-за каких-то костылей под responsive images.
    • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        чтобы контролы работали максимально быстро нужно в тегах прописывать onclick, а не биндить события скриптом. Хотя сейчас это считается плохой практикой, а жаль.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Наблюдал, как картинки с тормозного внешнего хоста «откладывали» загрузку js, и получалось, что все показывается, но не кликается.

            Обязательно поделитесь таким примером с общественностью. Прошу, хотя бы мне отправьте!
            • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Не могу понять — чем это лучше @ media в CSS? Или там загружаются ВСЕ картинки, не зависимо от media query?
    • +2
      Ага — грузит все
  • +1
    Спасибо за статью!

    — Майк из Mobify
    • 0
      У Вас там много русских, я смотрю. CEO, например. Я недавно с ним общался =)
    • 0
      Может расскажете нам поподробнее как это работает? Какие проблемы?
  • 0
    Прикольно. Ghostery заблокировал mobify.js на mobify.com. При этом сам скрипт в катгории «Advertising».
    • +1
      Напишу им об этом! Нет никаких причин блокировать.
  • 0
    хорошая штуковина, жаль что Internet Explorer 10+
    • 0
      Ага. Я тоже считаю это основным минусом.

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