Оптимизация обработки сложных селекторов

Original author: Joshua Peek
  • Translation
CSS селекторы в фронтенде можно сравнить с SQL операторами в бэкенде. Не смотря на их изначальную роль в CSS, мы активно используем селекторы в нашем Javascript коде, и, учитывая декларативный стиль селекторов, они являются приоритетными кандидатами на оптимизацию.

В браузерах существует много вариантов парсинга, обработки и сопоставления большого количества CSS селекторов. Современные веб-приложения используют тысячи селекторов в своих стилях. Чтобы рассчитать стиль для одного элемента, приходится учитывать огромное количество CSS правил. И браузеры не просто обходят все селекторы по кругу – это было бы очень медленно.

Многие браузеры используют специальную группировку данных, отбрасывая селекторы, которые очевидным образом не подойдут. В WebKit-е это выполняет RuleSet.

SelectorSet


SelectorSet – это Javascript-имплементация подобной группировки. Если у вас есть набор селекторов, известных заранее – вы можете производить выборку элементов по этим селекторам намного эффективнее.

Добавленные в набор селекторы анализируются и индексируются по ключу. Ключ формируется из значительной правой части селектора. Если селектор нацелен на id – этот id становится ключом, если в правой части класс, используется класс, и т.д. Затем селектор помещается в хеш, проиндексированный ключами. Поиск ключей в таком хеше происходит довольно быстро.

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

Как мы можем этим воспользоваться?

Ускоряем делегированные события


Наверное, самый известный пример делегирования, это функция jQuery $.fn.live (новое $.fn.on). Основное преимущество использования делегированного обработчика события, вместо привязанного напрямую, является то, что все новые элементы, добавленные после события DOMContentLoaded, будут также вызывать этот обработчик. Подобный подход часто просто незаменим. К примеру, в таком паттерне, как pjax, когда вся страница никогда не перегружается.

Но чрезмерное делегирование событий на document, таких как $(‘.foo’).live(‘click’), или $(document).on(‘click’, ‘.foo’) — чревато. Основной проблемой является то, что селектору приходится обходить всю цепь предков элемента, вызвавшего событие. В крупных приложениях с большими и сложными DOM, уровень вложенности может быть 15 и выше. Но это не самое печальное. Самое интересное начинается, когда делегированных селекторов становится много. GitHub использует более 100, а Basecamp – более 300 обработчиков событий, делегированных на document.

Но,


если сюда применить вышеописанный подход группировки селекторов, в виде патча к jQuery, можно значительно увеличить обработку событий в вашем приложении. Оцените разницу в небольшом тесте, в котором используются реальные разметка и селекторы с GitHub. В Chrome 32.0.1700 увеличение скорости обработки таких событий достигает 175%!

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

Ссылки на используемые библиотеки
github.com/josh/selector-set
github.com/josh/jquery-selector-set
  • +12
  • 12.6k
  • 7
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 7

    +9
    Я ничего не понял?
      –5
      Тест смотрели?
        +1
        Он строит структуру данных для быстрой выборки. Типа вместо того, чтобы брать дом элемент прогоняя на каждый селектор в отдельности, он берет хэширует его и затем уже сравнивает в своем Set'е есть ли что-то похожее и уже внутри делает полное сравнение на соответствие, насколько я понял.

        Ну типа очень неплохо(судя по тестам), хотя я бы просто не советовал бы ставить дом селекторы всегда на документ, впрочем когда у тебя Realtime без перезагрузки видимо только так и можно.

        Правда — да, не tutorial, и к CSS не считая селекторов, никакого отношения не имеет.
        +3
        О чем/к чему вообще текст выше? Где примеры плохих и хороших практик, сравнивание, анализирование?

        ~5 ссылок и информация о том, что подход к выборке по селектору может отличатся от браузера к браузеру — это не статья.
          +2
          Ну, это перевод статьи одного из разработчиков GitHub, который, на примере использования двух библиотек, показывает, как можно ускорить обработку делегированных событий jQuery почти в 100 раз.

          Мне очень понравился результат использования в нашем проекте, поэтому я решил поделиться этим тут.
            0
            хорошо бы добавить, что это удачное решение для SPA, либо для страниц с кучей js логики. Кто-то почитает и воткнет на свою домашнюю страничку и будет удивляться почему все стало еще хуже.

            з.ы. хаб CSS может убрать?
              0
              Предполагается, что человек, читающий такой материал, разбирается в теме, и не станет лепить все направо и налево, не вникнув в суть ). Хаб убрал, спасибо.

        Only users with full accounts can post comments. Log in, please.