📜 ⬆️ ⬇️

Optimization of processing complex selectors

CSS selectors in the frontend can be compared with SQL operators in the backend. Despite their initial role in CSS, we actively use selectors in our Javascript code, and, given the declarative style of selectors, they are priority candidates for optimization.

In browsers there are many options for parsing, processing and matching a large number of CSS selectors. Modern web applications use thousands of selectors in their styles. To calculate the style for one element, you have to take into account a huge number of CSS rules. And browsers do not just bypass all the selectors in a circle - that would be very slow.

Many browsers use a special grouping of data, discarding selectors that obviously will not work. In WebKit, this is the RuleSet .
')

Selectorset


SelectorSet is a Javascript implementation of a similar grouping. If you have a set of selectors that are known in advance, you can sample items by these selectors much more efficiently.

The selectors added to the set are analyzed and indexed by key. The key is formed from the large right side of the selector. If the selector is aimed at id - this id becomes the key, if on the right side of the class, the class is used, etc. Then the selector is placed in the hash indexed by the keys. Finding keys in such a hash happens pretty quickly.

The idea is that during the matching of an element and a group of selectors, the properties of the element are analyzed for the possible presence of keys. These keys are then searched in the hash, returning a smaller set of selectors, which are already used for a complete search for matching the element and the selector.

How can we take advantage of this?

Accelerate delegated events


Probably the most famous example of delegation is the jQuery function $.fn.live (the new $.fn.on ). The main advantage of using a delegated event handler, instead of being directly bound, is that all new elements added after the DOMContentLoaded event will also call this handler. Such an approach is often simply irreplaceable. For example, in a pattern like pjax , when the whole page is never overloaded.

But excessive delegation of events to the document , such as $('.foo').live('click') , or $(document).on('click', '.foo') is fraught. The main problem is that the selector has to bypass the entire chain of ancestors of the element that caused the event. In large applications with large and complex DOM, the nesting level can be 15 or higher. But this is not the saddest thing. The most interesting begins when delegated selectors become a lot. GitHub uses more than 100, and Basecamp uses more than 300 event handlers delegated to the document .

But,


if you apply the above approach of grouping selectors, in the form of a patch to jQuery , you can significantly increase the event handling in your application. Assess the difference in a small test that uses real markup and selectors with GitHub. In Chrome 32.0.1700, an increase in the speed of processing such events reaches 175% !

In fact, both of these libraries should be replaced by the means of the browsers themselves. They, of course, are already using their approaches to optimizing CSS, but, sadly, they still have no native implementation of declarative event handlers, although some people have been using this since 2006 .

Links to used libraries
github.com/josh/selector-set
github.com/josh/jquery-selector-set

Source: https://habr.com/ru/post/210270/


All Articles