tl;dr wp-emoji.js creates expensive event listeners that run every time you touch the DOM and it gives you no way to disable them.
At 1Pass we like to replace HTML with other HTML. That’s how we put the full text of articles onto publisher’s pages so our users can read them without buying subscriptions.
This afternoon my colleague @benilovj and I found a problem. Recently on The Browser, content was taking up to 9 seconds to replace. 9 seconds. And during those 9 seconds, the computer would become essentially unresponsive.
A few `console.log`s later, we found the problem here:
render: (article) -> el = document.querySelector(article.selector) el.innerHTML = article.content
This function returned more or less instantly. But the page lay around on the screen— burning hot, like the rest of the laptop—for a good few seconds before the content would show up. The machine started responding slowly, and the spinning beach ball of death would look in sometimes.
WP Emoji was to blame
This is not a terrible idea. Every time something adds content to the DOM, like infinite scroll, for example, it’ll have its emoji sprayed on automatically. In our case, as we injected our blob of HTML which was the article, wp emoji went bananas parsing every last little bit of it for smiles (that weren’t there).
Really, all this would be fine—convenience over configuration and all—if it weren’t for one fatal oversight. The only way to disable these observers is to get a reference to them and disconnect() it. But in wp-emoji, when the observer is created it’s just new’d up into oblivion. No reference is retained. And that means there is no way to unhook it except by some uncomfortable hacking. And without that, it murders performance for us.
Our library is designed to run on sites we don’t control, so we don’t have the liberty of installing the emoji disabling plugin.
All this… for emoji?