Have you ever tried optimizing your WordPress site and then Google Page Speed Analysis tells you that your website “Does not use passive listeners to improve scrolling performance “. How DO you fix that? Let’s Discuss what passive listeners are and how to fix this in WordPress.
When you go to scroll a page and there’s a touch event listener (wheel
, mousewheel
, touchstart
, touchmove
, etc.), the browser will not scroll immediately until it knows that the listener isn’t going to prevent the default scroll behavior. It doesn’t want to start scrolling prematurely, only to find out the listener eventually calls preventDefault()
) because it wants to do something different.
Example: Cancelling the scroll altogether when interacting with an embedded Google Map
So this is where passive event listeners come in.
By adding a {passive: true}
flag to the event listener, we can now tell the browser the listener will NOT cancel the default scroll behavior, and it’s safe to scroll immediately.
If you check your website on google page speed insights you may see this.
The problem is with the core WordPress comment system. WordPress (js/comment-reply.min.js) generating “non-passive” listeners. The script is responsible for comments UI features, in specific enabling users to comment in reply to another comment (i.e. nested commenting).
The problem with “non-passive” listeners is that they can slow down simple user interactions such as scrolling.
If you don’t allow nested comments anyway, you could simply remove this script from loading.
So How to fix this ?
Here is how you can remove the script from loading. But one thing to remember if you unload this, the nested comment will not work.
function wp_dereg_script_comment_reply(){wp_deregister_script( 'comment-reply' );} add_action('init','wp_dereg_script_comment_reply');
You can add this code in your function.php and it will be done.
How to Add a Passive Listeners for this?
The following code should be added in your .js file, or inside a <script> tag in every page (.e.g in header.php) or even as a tag in TagManager if you use that.
//Function checks if a given script is already loaded function isScriptLoaded(src){ return document.querySelector('script[src="' + src + '"]') ? true : false; } //When a reply link is clicked, check if reply-script is loaded. If not, load it and emulate the click $('.comment-reply-link').click(function(){ if(!(isScriptLoaded("/wp-includes/js/comment-reply.min.js"))){ var script = document.createElement('script'); script.src = "/wp-includes/js/comment-reply.min.js"; script.onload = emRepClick($(this).attr('data-commentid')); document.head.appendChild(script); } }); //Function waits 50 ms before it emulates a click on the relevant reply link now that the reply script is loaded function emRepClick(comId) { sleep(50).then(() => { document.querySelectorAll('[data-commentid="'+comId+'"]')[0].dispatchEvent(new Event('click')); }); } //Function does nothing, for a given amount of time function sleep (time) { return new Promise((resolve) => setTimeout(resolve, time)); }
Conclusion
Hopefully, WordPress.org core contributors can come up with something official but till then we need to do this manually to make our site more google friendly and improve scroll performance using these code snippets to add Passive Event Listeners