In most WordPress cases, minimizing main-thread work involves reducing (and optimizing) CSS/JavaScript, including third-party code and jQuery.
PSI tells you whether the main-thread is blocked by CSS/JavaScript or other tasks, but I recommend the Chrome Dev Tools coverage report to see CSS/JS files taking longest to load.
In WordPress, the main-thread is commonly blocked by bloated tools (themes, plugins, and page builders that add CSS/JS) as well as third-party JavaScript. If you’re not able to remove these, you can try hosting third-party JavaScript locally or delaying it, activating built-in page builder optimizations, and using Perfmatters to remove unused CSS and unload unused assets.
While there are other optimizations that can help, I recommend tackling this at the source by making sure you’re on a lightweight setup. Otherwise, there are more files you have to optimize.
For best results, we’ll be using Perfmatters for the script manager, removing unused CSS, finding jQuery-dependent plugins, optimizing fonts/analytics, lazy loading CSS background images, and other optimizations which help minimize main-thread work.
- Find your longest tasks
- Avoid bloated themes, page builders, plugins
- Activate built-in page builder optimizations
- Don’t use page builders for your header, footer, sidebar
- Unload CSS/JavaScript
- Remove jQuery-dependent plugins
- Remove unused CSS (but not in WP Rocket)
- Use local fonts, analytics, YouTube thumbnails
- Delay remaining third-party JavaScript
- Remove Gutenberg CSS if you don’t use it
- Lazy load background images
- Reconsider animations
- Disable icons or use custom icons
- Minify CSS + JavaScript
- Defer non-critical CSS + JavaScript
- Reduce memory usage
1. Find Your Longest Tasks
The diagnostics section of PSI shows “avoid long main-thread tasks.” However, it doesn’t show which specific files are blocking the main-thread. That’s why I recommend the coverage report of Chrome Dev Tools which shows your largest CSS/JavaScript files, their total bytes, and usage.
2. Avoid Bloated Themes, Page Builders, Plugins
Elementor, Divi, and Avada add lots of CSS/JS which can flag several PSI items. This is a big reason page builders got crushed during web vitals and started taking speed more seriously.
While it’s best to go with lightweight alternatives like GeneratePress/Kadence, ditching your page builder may not be on the list. Here are a few things you can do to optimize page builders:
- Active Elementor Experiments or Divi Performance settings.
- Limit the number of Elementor columns/widgets (see this video).
- Code your header, footer, and sidebar in CSS (don’t use page builders).
- Don’t go crazy with adding page builder plugins – it’s a recipe for disaster.
- Elementor and host fonts locally and preload them in the performance settings.
3. Activate Built-In Page Builder Optimizations
Elementor and Divi both have built-in optimization settings that help reduce CSS/JavaScript. Here’s a test I did on an Astra Starter Site with Elementor’s Experiments enabled vs. disabled:
4. Don’t Use Page Builders For Your Header, Footer, Sidebar
If you must use a page builder, code these in CSS.
You can use page builders to create pages, but these appear across your site. CSS is less bloated than page builder code and this was the first thing WP Johnny did when I hired him to remove Elementor, which dropped mentions of “Elementor” in my source code from about 2,000 to 200.
Makes a big difference!
5. Unload CSS/JavaScript
I use the Perfmatters script manager, but Asset CleanUp is fine too.
Once the script manager is activated in the settings, view any page/post on your site and find the script manager. It will show you all CSS/JavaScript files loading on that page. Sometimes, plugins load across your entire site even when they’re not being used on specific pages, which means you can safely disable them where they’re not used. Make sure to enable test mode to prevent things from breaking your site while testing this out. Here are a few common examples:
- Disable social sharing plugin everywhere but posts.
- Disable contact form plugin everywhere but contact page.
- Disable page builder plugins everywhere except current URL(s).
- Disable page builder plugins everywhere except current URL(s).
6. Remove jQuery-Dependent Plugins
If you’re using a lot of jQuery-dependent plugins, it can be the longest main-thread task:
To find which plugins use jQuery, select display dependencies in the script manager settings of Perfmatters.
Now when you go to your script manager, you will “jQuery” and all plugins requiring it. This is another reason I don’t recommend page builder plugins, because look at how many use jQuery:
7. Remove Unused CSS (But Not In WP Rocket)
Perfmatters, FlyingPress, and LiteSpeed Cache are more effective at “removing unused CSS” than WP Rocket.
While the first 3 plugins load used CSS in a separate file, WP Rocket loads it inline. So not only can it not be cached, but it increases the size of HTML. As the Perfmatters documentation says, the “inline” method is better for scores, but the “separate file” method is faster for actual users.
When I pointed this out to WP Rocket, they insisted inline was better even though every other expert says otherwise, including Vikas Sharma who you probably know from Facebook Groups:
8. Use Local Fonts, Analytics, YouTube Thumbnails
Third-party code is one of the biggest culprits of main-thread blocking time, especially when you’re using lots of third-party tracking tools like Google Analytics, Tag Manager, and Heatmaps.
Luckily, we can host fonts, Google Analytics, and YouTube thumbnails locally.
- Google Fonts – instead of pulling fonts from fonts.gstatic.com, host them locally using plugins like Elementor, Perfmatters, FlyingPress, and OMGF. It’s also better for GDPR compliance. On a side note, make sure to test preloading fonts loading above the fold or located in CSS, use font-display: swap (or optional), and woff2.
- Google Analytics – Perfmatters and Flying Analytics are great for this. Not only can they host Google Analytics locally, but they allow a smaller tracking code and can disable remarketing features which eliminates a 2nd request to DoubleClick.
- YouTube – FlyingPress is the only plugin I know that hosts YouTube thumbnails locally using a placeholder which eliminates requests to i.ytimg.com. Of course, you should also lazy load videos and replace their iframes with a preview image.
9. Delay Remaining Third-Party JavaScript
Once you’ve removed unnecessary third-party code and hosted files locally, you should be able to delay the rest if it loads below the fold. This is the benefit of pushing third-party code down on the page (like ads and social sharing plugins) since delaying it makes your page much faster.
Most (premium) cache plugins do this nowadays, but SiteGround Optimizer and most cache plugins don’t, in which case, use Flying Scripts.
Whichever plugin you use to delay JS, check their documentation on how to add them as well as my list of common JS files to delay. WP Rocket does it automatically, LiteSpeed Cache does this with their “localize resources” settings, and Perfmatters + FlyingPress make you add files manually but allow for more control for things like the timeout period, which I usually set to 5s.
10. Remove Gutenberg CSS If You Don’t Use It
If you don’t use Gutenberg blocks, you can dequeue the block library (otherwise block-library/style.min.css loads across your site). Add this to functions.php or with Code Snippets.
<?php
// Fully Disable Gutenberg editor.
add_filter('use_block_editor_for_post_type', '__return_false', 10);
// Don't load Gutenberg-related stylesheets.
add_action( 'wp_enqueue_scripts', 'remove_block_css', 100 );
function remove_block_css() {
wp_dequeue_style( 'wp-block-library' ); // Wordpress core
wp_dequeue_style( 'wp-block-library-theme' ); // Wordpress core
wp_dequeue_style( 'wc-block-style' ); // WooCommerce
wp_dequeue_style( 'storefront-gutenberg-blocks' ); // Storefront theme
}
11. Lazy Load Background Images
Since page builders (like Elementor) load background images from CSS, they’re not lazy loaded by default which can significantly increase the page size.
If you’re already using Perfmatters, it can lazy load CSS background images. If you’re not, some cache plugins have a lazy-bg or skip-lazy class you can add to background images (which one you use depends if they load in above the fold vs. below). Optimole has similar settings as well.
12. Reconsider Animations
Google says:
“If any animation triggers paint, layout, or both, the “main thread” will be required to do work. This is true for both CSS & JavaScript-based animations… see CSS Triggers.”
13. Disable Icons Or Use Custom Icons
Font Awesome and Elementor’s Eicons add more CSS. You can disable them (use the code below to disable Eicons), or disable them and use custom icons in Elementor → Custom Icons.
add_action( 'wp_enqueue_scripts', 'remove_default_stylesheet', 20 );
function remove_default_stylesheet() {
wp_deregister_style( 'elementor-icons' );
}
14. Minify CSS + JavaScript
Minifying CSS/JS strips unnecessary characters, reducing files sizes and main-thread work.
Combining them isn’t usually recommended. WP Johnny explains whether or not to combine CSS/JS but basically, you should only combine if your site has a very small amount – like 10KB.
15. Defer Non-Critical CSS + JavaScript
Deferring CSS and JavaScript can eliminate render-blocking resources.
WP Rocket and other cache plugins usually have a ‘load JavaScript deferred’ option. If this doesn’t give you great results, try Autoptimize along with Async JavaScript. For me, this gave me better results than when I used WP Rocket. Make sure you “apply defer” in Async JavaScript.
16. Reduce Memory Usage
Reducing CPU/memory usage lets your server spend more effort on the main-thread and less work on unnecessary tasks.
This is common with shared hosting and as an example, there are tons of people in Facebook Groups who posted how they left SiteGround (one of the worst) and instantly fixed CPU issues. Login to your hosting dashboard, check CPU usage, and make sure it’s nowhere close to 100%.
- Remove high CPU plugins.
- Disable Heartbeat + XML-RPC.
- Increase the autosave interval.
- Use a CDN to offload resources.
- Use full page caching if possible.
- Move and protect the wp-login page.
- Block bad bots from hitting your site.
- Replace wp-cron with a real cron job.
- Use OPcache (Google it for your host).
- Schedule ongoing database cleanups.
- Disable usage tracking in plugin settings.
- Disable or limit preloading in cache plugins.
- Only preload important sitemap URLs, not the full sitemap.
- Don’t trigger actions that make your cache plugin clear the entire cache.
Frequently Asked Questions
How do I minimize main-thread work in WordPress?
WordPress sites can minimize main-thread work by reducing CSS/JS from bloated themes/plugins (especially jQuery-dependent plugins) and delaying third-party JS.
How do I minimize main-thread work with WP Rocket?
While WP Rocket helps minimize main-thread work through settings like deferring/delaying JavaScript and minification, it can't host fonts locally and the remove unused CSS setting is inferior compared to other cache plugins, as it loads used CSS inline which can't be cached.
How do I minimize main-thread work on mobile?
Coding your header in CSS, unloading CSS/JS on mobile, and simplifying your mobile design with less widgets/columns can help minimize main-thread work on mobile devices.
Cheers,
Tom