In the scope of things that can slow down your website, I would put JavaScript (JS) at a solid #2. One of the biggest problems with optimizing JavaScript is that folks don’t understand it, and often don’t see it. That is, you can see the effects of what JS does on your site, or even see that your site is slow, but it isn’t as obvious as images, CSS, or fonts. JS flies under the radar, but can wreak havoc on the performance and user experience of your website.
Fortunately, there are several things we can do to solve problems with JavaScript. We can compress it, defer it, delay it, or even just get rid of it entirely. We’ll look at all of these and more in our quest to speed up our sites. Along the way, we’ll even look at things you shouldn’t do with the JS on your site. Like calling it Java, because that’s something else entirely, and not something you’ll encounter on a WordPress website.
Quick Wins
Just as with CSS, there are some things every site can do to optimize the JavaScript on every site. These are usually done already, but it’s good to be aware of them so you can start off on the right foot.
First off, all the JS on a site should be minified. This means removing all excess whitespace to make the JS files as small as possible. This also may involve renaming variables, and other tricks to shorten the JS code. You don’t usually need to know the details, and most plugins and themes will already have their JS minified.
If you do have some unminified JS, plugins like Autoptimize, Perfmattters, and our own SWIS Performance can take care of that for you. Additionally, if you use our Easy IO CDN for your images, it also double-checks your JS to make sure it is minified. If you want to double-check, look to see if the filename contains ‘.min’ or look at the code, and you should see something that looks completely unreadable like so:

Another way to save even more space on your JS files is with Gzip or Brotli compression. This is like zipping up your JS before sending it to your visitor, and is often already enabled. Or at least, it should be on any decent web host. Even if it isn’t, you can install our SWIS Performance plugin and it will automatically attempt to enable Gzip compression on your server for CSS, JS, and HTML.
You can use the Network tab in your browser’s Developer Tools to confirm if your JS is compressed. When you click on a particular JS file, you’ll see how much was transferred, and the actual size of the JS once it is uncompressed. Compare the “34.1 kB transferred” (lower right) with “91.1 kB resources”, which tells us the file was compressed.

Additionally, you can look at the Content-Encoding header (right-side) and look for gz or br to see that Gzip or Brotli compression was used.
Lastly, JS can benefit from loading files in parallel. Especially if there are more than a couple JS files on your site, this makes a big difference. Fortunately, every browser, and most hosting platforms support this by default. There are a couple prerequisites though: your site must be using HTTPS with a TLS/SSL certificate. This is free on most web hosts, so there’s really no reason not to do this anymore. Also, your site needs to be using the HTTP/2 protocol (or better) in order to really get the best performance. Old school HTTP/1.1 can kind of, sort of, do parallel transfers. But, it’s a mere shadow of the implementation in HTTP/2, which has been out for years and ought to be used by every web host.
Taboo – Merging JS
Please don’t, really, just stop it already… Once upon a time, you may have seen it recommended to merge all your JS into a single file. That was great when we were all using HTTP/1.x–and even then, was really just slapping a bandage on the problem. Now HTTP/2 is pretty much everywhere (or should be), and combining JS usually just slows things down. Instead of a dozen small downloads all happening at once, merging JS causes one single, large, and slow download instead.
Worse, it negates the benefits of browser caching. So if you change or update a plugin, or your theme, or maybe even WordPress, then your combined JS file needs updated, and every visitor has to re-download all of your JS again. Gross!
Slow it Down!
Wait, what!? I thought we were trying to speed up our sites? First, lets explain the problem briefly. Depending on where a given JS file is inserted in the HTML of your page, it can cause “render-blocking”. That is, the browser may have to wait until the JS file is loaded and executed before it can display the page to the user. Specifically, any HTML or CSS that comes after a JS file cannot be rendered until the JS is run. So, one of the best things we can do with JS is to make it load later, or further down the page. It isn’t really “slower”, but making sure all the HTML and CSS is loaded first allows the browser to render the page without waiting around for our JS.
Unsurprisingly then, of the oldest methods for preventing “render-blocking” JS was to make sure it was at the bottom/footer of the page. Many plugins do this by default, but unfortunately, sometimes it still ends up in the “head” of the page. Never fear, it doesn’t really matter anymore, because we can prevent render-blocking by deferring or delaying JS!
Defer it?
Yes, do this! There are actually two different methods, ‘defer’ and ‘async’, but we’ll focus on ‘defer’ since that is usually the safer option. Deferring JavaScript makes sure that the browser doesn’t pause or wait to render the page when it finds a JS reference in your page. Instead, it downloads JS in the background, and when the page has been rendered, the JS is finally run. This is great for user-experience, as the page can be rendered much quicker, almost instantly if Critical CSS is in use. The ability to defer JS is built into WordPress now, but plugins have to opt-in for it to work. So…

In our SWIS Performance plugin, just enable Optimize JS Loading, and that’s it! Well, usually… See, the ordering of JS on a page is important, and if one bit of JS depends on another JS, and their order gets mixed up, then the first bit breaks and stops right where it is. This can leave all sorts of functionality broken. Normally, deferred JS is executed in the same order as it is found in the page, and everything is awesome.
Unfortunately, many plugins make use of inline JavaScript. For small bits of code, or dynamic bits that are based on the site configuration, the JS is dumped right inline with the HTML instead of loaded through an external file. By default, inline JS cannot be deferred, and that whole execution order goes out the window. In SWIS, we rewrite the inline JS to use the same syntax as external JS, using a ‘src’ attribute. It’s still “inline”, but it can now be deferred just like the external JS, and then the execution order is preserved.
Even then, some plugins come up with clever ways of inserting JS, or they use syntax that SWIS can’t handle, and things get squirrelly. If you do run into something like that, let us know and we’ll see if it can be fixed.
Or Delay it?
Delaying JS is not a browser-native thing, but many performance plugins include this ability. Delaying JS allows it to be downloaded normally, but prevents it from executing until the user does something with the page, like scrolling or clicking. However, it is dangerous and prone to breaking things, especially menus that need to open on hover or click. Because the JS hasn’t run yet, the menu won’t operate until after the first click, then they have to click again, or maybe once more until it actually works.
There is another potential problem with delaying all of your JavaScript. But let’s backup a second to see the different user experiences. With normal loading, JS is running here there and everywhere, potentially spread out, but likely with some of it render-blocking. When you defer, all of it loads as soon as the page has been rendered. This potentially gives the browser a little time to get JS executed before the user tries to interact with the page, but if you have a lot of JS, that might leave the user clicking or scrolling with nothing happening. You’ll see this referred to as “input delay“, and it isn’t great for our users.
Now, if we delay all of our JS, we are already waiting until the user interacts with the page, and now nothing will happen when they click or scroll until all of the JS has executed. Some plugins move JS off the “main thread” to avoid this, but that masks the problem of too much JS. It’s still using up CPU on the client and can cause bottlenecks. Instead, SWIS will allow you to choose to delay JS selectively instead of delaying everything. We recommend you start with deferring all your JS, and then use the Slim panel to delay scripts that don’t need to run right away on the page.
Toss it!
Those are all the easy things, and the slightly less easy things–or things that require a plugin. What if you have JS that is loading on your page, but isn’t even being used. Yes, this happens more than I’d like to think. It shouldn’t anymore, as plugins/themes should detect when a particular JS file is necessary, and only load it on select pages.

Unfortunately, some developers don’t bother with making things work properly, so we either have JS that isn’t used at all, or JS that only needs to load on one or two pages. In all of those cases, Google (and others) will tell you to get rid of it, but how? There are several plugins that can help you out with this, and SWIS Performance is one of those. Do note this is not a one-click thing and you’re done. Doing this properly takes time, so only mess with it if you have that time to spend.
Finely Tuned
All of these things will help your site look like the finely-tuned machine that it ought to be. Many are quicker, or at least easier, but all of them can help your site load faster, and work better for your visitors. As always, keep your focus on them. Don’t do it for a higher score, or the promise of better SEO, do it for the people that you will impact with a better website.