Quick chat I had with a friend…
Why shouldn’t I combine CSS styles and JS scripts?
To combine/merge or not. It’s an endless debate over which is better.
Merging CSS/JS looks great on performance test sites like Pingdom and GTmetrix but is it really the best performance for your site?
STOP Merging CSS/JS!
Reason #1 – it slows down your site load!
For me, merging CSS is a superficial improvement that makes your test scores look better since you have fewer requests. These page speed tests were only intended to be used as guidelines. Many of them (if not all) were designed before the new HTTP/2 protocol.
[Brief] history of evolution from HTTP to HTTP/2 protocol
- Old HTTP protocol could only load a few requests at a time, queuing the other requests (imagine 1 cashier with many customers in line). So in those days, it was better to have fewer HTTP requests. Tactics like “CSS sprites” and combining CSS/JS was standard practice. With only one cashier, having one giant order was faster than several small orders, each with their own transactional overhead in DNS request times.
- HTTP/2 protocol came out allowing parallel requests (imagine multiple cashiers instead of one). With multiple cashiers, requests were served quicker as separate smaller requests rather than combined. HTTP/2 gave such massive performance increases, you would expect almost immediate adoption. Unfortunately, it required HTTPS (TLS/SSL certificates) which weren’t yet standardized (also cost money/skills to implement).
- As expected, low-budget webhosting clients weren’t willing to pay for SSL or deal with technical hassles of setup/renewal for them. They also weren’t necessarily if you didn’t have a store. (At the time, no 1-click solution existed for installing TLS/SSL certificates; you had to copy-paste long bits of encrypted text and wonder if you did it right.)
- But then the industry changed…Google started requiring all websites to have HTTPS or risk being penalized on their search engine rankings. The only one thing left in the way was affordable TLS/SSL certificates. Luckily for everyone, Let’s Encrypt came out with free TLS/SSL certificates—HOORAY! Webhosts started offering 1-click solutions overnight and HTTPS (alongside with HTTP/2) became the standard.
- While the webhosting and web-browser industry made HTTP/2 and HTTPS standard; outdated page speed tests (and many speed-up guides) are still recommended practices like decreasing the number of requests. We are still living in that conflicted aftermath today. For the record: I’m all for decreasing code and even requests; I just don’t see the point of wasting precious server resources to combine code into one lump file that takes longer to process.
People think that because their server sent out fewer requests, it means their server did less work…but that is false thinking. Your server sends out the same amount of code no matter what. If anything, your server may work harder because you merged. Merging CSS also has a few annoying issues…instead of letting your page render immediately, it now has to wait for your entire CSS to load.
Imagine eating at a restaurant with 20 friends. Do you want the food to come out as soon as it’s ready? Or only when everyone’s order is cooked?
For me…most CSS should be loaded as fast as possible and most JS should be as delayed as possible (UNLESS, there is critical JS like being used for slider above the fold).
As for merging JS (scripts)….I think it’s great if your merging mechanism can also defer and throw them to the footer (that’s the only reason why I would merge them). But in general…and especially with well-coded sites, you don’t want it.
Reason #2 – it breaks your site
You’ll end up spending a lot of time troubleshooting sites with broken CSS/JS merges. I see “cache plugin broke my site” on WordPress Facebook groups about 2 dozen times every week.
And even if things do look alright, the site might not be perfect and or might not always get performance benefits. Your contact form might break, or some scroll function, or some ajax function. There’s a myriad of possible conflicts that can happen when you merge JS.
Reason #3 – it adds unnecessary page load
- Plain pages will load your pagebuilder.
- Pages that aren’t related to your store or products will load WooCommerce.
- Pages that don’t have any forms loaded will load your forms anyway.
And so forth. Imagine if you had 30-40 plugins, well guess what…now your site loads all the CSS/JS on every single page. How wasteful!
Ok fine…there are some “intelligent” CSS/JS merges that allow separate CSS/JS for every page but now this is overkill. Your server spends more time merging CSS/JS than actually serving pages to users. Feel free to experiment on your own but my general rule is not to merge JS.
Reason #4 – it delays cache prebuild
There’s a million tactics and it’s kind of an art in itself. Depends on what kind of site, what kind of traffic, and how often you update content.
PS: those test sites are a little bit dated. Giving suggestions that would have worked better for older webhosting technology.
“Doesn’t combining CSS/JS reduce the code?”
Yes, it’s true! Merging your CSS/JS often reduces code, stripping out empty spaces and unnecessary code. So it would seem like your site would load faster since there’s less code overall to load. Only problem is, that’s not how pages render.
You see, pages render as soon as an entire asset loads.
- Let’s compare uncombined CSS (split1.css + split2.css + split3.css = 60kb total) vs combined CSS (combined.css = 50kb).
It’s reasonable to think the combined css would load faster because it’s smaller, but that doesn’t always happen. There’s a good chance your site can start rendering the page with only split1.css (with split2.css & split3.css being used to render lower parts of the page). If that’s the case, you’re better off leaving the files uncombined so the page renders earlier for users. The idea here is to start rendering soon rather than finish rendering sooner. (It’s basically the concept behind “Critical CSS“.)
“But the combined CSS doesn’t have to load if it’s cached!”
That’s a great point, too. If you combine the CSS/JS and then cached it to the user’s browser locally, they wouldn’t have to download it! The only problem is…most visits to your site are going to be 1st-time visits. Even if it was just one person…they could be visiting from their desktop, their laptop, their mobile phone. Maybe a different browser, or maybe their cache cleared. Whatever reason it is, the majority of your traffic will be first-time visits.
Here’s another thing…you can cache uncombined CSS/JS files, too! Put long expiry times on them and it’s pretty much the same thing.
“What about Critical CSS?”
If your site is bloated to the point where you actually have critical CSS vs non-critical CSS, you have a different problem. Clean up your code. If your total CSS is only 40-50kb, that’s fine. Leave it un-merged.
“Are you sure about NOT merging JS?”
The topic of merging JS is a whole can of worms in itself. Let’s start with the pros and cons. Right off the bat…merging JS is always a darn risk because something breaks in your site. Second, we’re now in the age of HTTP2 where loading multiple assets in parallel beats loading one combined asset. Those 2 reasons alone are good enough to avoid it. It’s a safer option with great performance and far less issues to fix.
So what’s the best way to manage JS and when should you merge JS?
I think most JS are not critical to initial page rendering. JS usually has to do more with the page’s function than its design. Note the operative word ‘usually’. Some JS does have to do with the design…such as image sliders, tab content, expandable/collapsible divs, pop-ups, etc.
Ideally, all JS (except for design-related JS placed above-the-fold) is deferred to the end of the page load queue and doesn’t load until the rest of your design loads first. Even better is if you can prevent certain JS from not loading at all unless the user scrolls to it or interacts with it (lazyload/onload-event)…this would be great for things like super bloated Googlemaps iframe laying at the bottom of the site.
Some of the merging mechanisms out there will do all that…combine your JS and defer it. And then you could manually exclude certain critical JS files from being merged and deferred. And also put some on lazyload if you wanted.
“But my site has faster speed scores with CSS/JS combined!”
This is a great reason many people use to justify combining CSS/JS. And in some cases, it’s true—combining CSS/JS might get you a faster FINISHING load time. But here’s the thing…what we want is faster STARTING load time.
Remember that whole trend about optimizing TTFB? It’s all about starting sooner, not finishing sooner. Having a fast response time can be just as important as a fast load time.
We want your pages to render quicker (not necessarily just to download quicker). The sooner your page renders, the faster the perceived load will be for users. This is why JS loading is such a finicky matter. Some items should load first, others should all be deferred so they don’t get in the way of critical JS items!
So decide…are you speed-optimizing your site for page scores or for users? (And FYI, it’s possible to do it for both…that’ll be a whole other guide later.)
Aren’t there any exceptions?
As with all things, yes. There are indeed exceptions but they are few and far between and still I wouldn’t recommend you to do it if you wanted a hassle-free caching experience.
Combining CSS/JS from the same theme or plugin makes sense!
If you’ve ever had a theme or pagebuilder plugin offer to combine its own CSS or JS. Yes, please enable that. It makes sense. As all CSS and JS coming from one extension is already compatible/harmonious with itself. Not only that but it can combine them natively without requiring extra server processing or mechanism to manage. It’s like choosing whether to carpool with roommates, or with friends that live all over town.
Combined CSS/JS files sometimes cache better
The key word is “sometimes”. Sometimes the combined file is more likely to hold it’s long expiry time, or hit Cloudflare’s DNS cache better. It depends on different scenarios. It’s always worth a shot if you’re not happy with your situation. The general idea is that the CSS file is cached on the user’s computer and no longer needs to be downloaded on subsequent requests. Only issue left is that even with this, your first load will still be slower as the merged CSS isn’t cached yet. Check your GA stats and if most visitors hit less than 1.5 pages, I probably wouldn’t merge.
Combining CSS/JS is worth it for small files
I especially don’t like when you combine a bunch of large 20kb CSS/JS files to make a giant 1MB file. But if you have a bunch of 0-3kb CSS/JS files, I think it’s ok to combine those. This is logical as small files cost more in DNS lookup time than they do in actual processing time.
Combined CSS/JS files sometimes has less conflicts
This has more to do with conflict resolution than performance. Sometimes, you may have a bunch of CSS or JS files conflicting with each other and breaking the site design or functions. Sometimes combining fixes that. It’s random but I’ve seen it happen.
Combined CSS/JS can speed up small sites when placed in-line
On really small/lightweight sites, the DNS resolution time is longer than the actual load time for the tiny CSS/JS files. In cases like this, it might be a good idea to just combine the CSS/JS code and place it inline with the html.
In this case, you’re speeding up the site not by combining CSS/JS but by reducing the number of HTTP requests. Again, this is only recommend for really lightweight pages! If you’re total CSS and JS is like 10kb or less, you may be a good candidate for this tactic.