Make WordPress Core

Opened 7 years ago

Closed 7 years ago

Last modified 3 years ago

#41405 closed enhancement (maybelater)

Only output Emoji JS when emoji used on page

Reported by: jhabdas's profile jhabdas Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Emoji Keywords: reporter-feedback
Focuses: Cc:

Description

Currently Core supports Emoji characters. Emoji are great, but not when they require an external asset request when none are used on a page.

This issue is to update Core to prevent the external JS request for the following:

/wp-includes/js/wp-emoji-release.min.js?ver=4.8

...when no Emoji is used on the page.

This should be considered a bug and not an enhancement as I wouldn't consider something feature complete if it adds page weight when not in use.

Orthogonal benefit of fixing this bug is limiting the need for the plug-ins arising to suppress the output of this script, thereby improving overall WP security and end-user experience.

Change History (6)

#1 @SergeyBiryukov
7 years ago

  • Component changed from General to Formatting

#2 follow-up: @pento
7 years ago

  • Component changed from Formatting to Emoji
  • Keywords reporter-feedback added
  • Version trunk deleted

Thank you for the bug report, @jhabdas!

So, there are two parts to the emoji rendering code. The first part is the tiny bit of JavaScript you see inline at the top of any WordPress page. This is the minified version of wp-emoji-loader.js, it detects if the current browser renders emoji correctly.

There are a few things to note about this code:

  • It's intentionally very small, to affect page download size as little as possible.
  • It's intentionally very fast, generally executing in a single browser tick (around 3ms), to affect page render speed as little as possible.
  • When it needs to load wp-emoji-release.min.js, it does so asynchronously, so that it doesn't get in the way of the page's primary render path.

Any changes need to be considered against those requirements.

Unfortunately, detecting emoji use is not as simple as checking for emoji in the_content, as they can appear anywhere on the page - in widgets, menus, headers, or even hardcoded in plugin or theme strings. So, the only option is to do what wp-emoji.js (which is part of wp-emoji-release.min.js) does - check the entire page content on the client side for emoji, and watch for any changes that include emoji.

The down side of wp-emoji-loader.js being loaded so early is that it blocks rendering for the time it's running, so if we were to move the content check to the loader (so we could make a smarter decision about loading wp-emoji-release.min.js), it's very likely that we'd be making the initial page render significantly slower for every page on every WordPress site.

And so, what we currently have is what we consider the best trade-off between performance, and unnecessary downloads.

We also find that the problem swings back and forth between loading, and not loading, depending on when we roll out support for new emoji, vs. when OSes roll out support - when new version of Android, iOS, and macOS are released, browsers on those platforms won't download the script anymore, because they're able to render the full range of emoji.

If you're absolutely certain that your site will never have emoji on it, and the emoji scripts are causing unacceptable performance issues, the best option is to install a plugin to disable WordPress' emoji rendering. This plugin is super simple, it just unhooks the actions and filters that WordPress uses to add emoji rendering support, so I wouldn't expect it to cause any security issues.

Now, all that said - have you noticed any particular performance issues with either the loader or the full emoji script? Is it blocking rendering for longer than it should, or causing unnecessary jitter while things are rendering? These are problems that we can, and absolutely should address. The emoji rendering script should be as invisible as possible to the normal end user experience.

#3 @jhabdas
7 years ago

  • Resolution set to maybelater
  • Status changed from new to closed
  • Type changed from defect (bug) to enhancement

@pento Great response. Sorry I didn't notice the async script loader while I was analyzing. The rest sounds pragmatic to me. Thanks for your time. Cheers.

#4 @netweb
7 years ago

  • Milestone Awaiting Review deleted

#5 in reply to: ↑ 2 @westonruter
3 years ago

Replying to pento:

  • It's intentionally very fast, generally executing in a single browser tick (around 3ms), to affect page render speed as little as possible.

Humm. I'm seeing that emoji-loader.js it's actually taking ~90ms and it is classified as a long task in Chrome DevTools:

https://core.trac.wordpress.org/raw-attachment/ticket/37788/long-task.png

ref 37788#comment:4.

#6 @pento
3 years ago

Interesting, that JavaScript still runs in well under 10ms for me in both Chrome and Firefox: I was able to slow it down a bit by throttling the network and CPU, but even then, it was still substantially less than 90ms.

It's worth noting that the Task you've highlighted will likely be slower than the emoji JavaScript, as it includes the entire HTML parsing step, and the load event.

I'm curious about why the toDataURL() calls seem to be very slow on your device, though. Do you see the same slowness without any extensions running? Have you disabled any of the GPU rendering or rasterization options in chrome://flags?

Note: See TracTickets for help on using tickets.