Plugins & Themes shouldn’t combine their external assets.
I am going to outline why plugins and themes should never combine or bundle their external JS and CSS libraries. Not only is this against best practice but it can have several detrimental effects down the line.
First as a plugin or theme developer for WP our jobs is not to conserve bandwidth. That is not to say that we shouldn’t error check & minify our own assets, but our job is to provide specific features and functionality in an optimized but accessible way.
Unless your plugin is a caching or speed up type of plugin such as W3 total cache or similar your job isn’t to worry about the sites page load beyond optimizing your own code. You don’t need to combine and minify other libraries.
Let me give you an example.
Plugin A uses jQuery cookie & jQuery Transit and bundles them into a single js file called plugin-a.tools.min.js.
Plugin A then registers their script like this
wp_register_script( 'plugin-a-tools', plugin_dir_path( __FILE__ ) . '/js/plugin-a.tools.min.js' );
They may even minify it for good measure.
They do this under the guise that they are helping the site owner lower their page load times by doing this for them. Good intentions.
The problem comes when the site owner then installs Plugin B & Plugin C which look like this.
Plugin B uses jQuery Cookie which they include as the original or minified version of the official latest version from git. They save it under the name jquery-cookie.min.js and register it like so
wp_register_script( 'jquery-cookie', plugin_dir_path( __FILE__ ) . '/js/jquery-cookie.min.js' );
Plugin C uses both jQuery Cookie & jQuery Transit as well. Like Plugin A they include each library in a custom file plugin-c.plugins.js.
wp_register_script( 'plugin-c-plugins', plugin_dir_path( __FILE__ ) . '/js/plugin-c.plugins.js' );
You may already see where this is going but if not let me demonstrate.
When the scripts are loaded this is what gets loaded to the users browser.
- jQuery Cookie
- jQuery Transit
- jQuery Cookie
- jQuery Transit
You can see the obvious dilemma here. All the load time they may have saved the user they have also now just added themselves. You now end up with 3 separate copies of jQuery Cookie, and 2 copies of jQuery Transit.
This can not only have a major impact on the load times they were attempting to reduce, but will lead to major JS errors in a lot of cases because multiple instances of each plugin are available and colliding.
As I said before our job is not to speed up loading. It is to optimize compatibility with other plugins and themes. In fact I dream of a world where my plugins are never incompatible.
Registering each library separately and keeping them up to date is both necessary and important.
This may not seem obvious at first glance reading through the WP codex, but there is a clearly visible design pattern in WordPress itself that shows this is the optimal way to do it, at least for WordPress products. Take the wp_register_script page for instance, specifically how they break up jquery ui into many parts rather than just jquery-ui. This is to minimize collisions. If it were meant to save loading they would simply load the full minified library instead as it would be one slightly larger request vs loading 30+ single files one at a time.
The solution is simple. If you need an external library in your product follow these guidelines:
Keep the library up to date.
All to often I see a plugin that is regularly updated, but has a 2 year old copy of jquery-cookie. Check often to see if there is a new version and update when necessary.
Register each as its own separate file with unique $handle.
Register each library with wp_register_script. Try to find other plugins that use the same library and see what $handle they use. If you don’t find one try to use one you think others might also use.
Be courteous to other authors
If another author contacts you about your $handle name being different than theirs, be courteous and try to find a common ground. Once found you can publish and persuade other authors to use the same handles increasing compatibility in the future. Until someone sets the standard there is none.
Leave combining & minification to the pros
Leave the combining and minification of the external library to the pros, the plugins developed specifically for that purpose. Include the libraries just as they come from their sources. If they include a minified version already feel free to use that.
Following these simple guidelines, plugins would almost never have compatibility issues caused by dependency libraries.
Plugin A, B & C would then all load without issues and there would be no more than 1 copy of jquery-transit & jquery-cookie loaded.
Daniel Iser is a professional WordPress plugin developer, and the author of plugins such as Easy Modal & Popup Maker. Founder of Wizard Internet Solutions he has been working with WordPress for over 7 years creating websites and tools for clients & blog authors.
I understand where you’re coming from on this, but I don’t 100% agree. As a theme developer, I believe that my responsibility is not with making the lives of developers easier, but with making the lives of users easier.
If I’m serving 10 different scripts in my theme, many of which are very specific to the theme and unlikely to be duplicated by a plugin, why should I force my users to figure out a solution to why they have 10 extra http requests every time their site loads? They don’t necessarily know why this is a problem and they certainly don’t necessarily know how to fix it.
It’s easy to say “well, they should use a cache plugin or a minifcation plugin to handle that”, but in the real world that doesn’t happen very often. If you want to create performant themes and plugins, sometimes you need to compromise and concatenate scripts. There are ways to handle this that make things a little easier on other developers, but generally speaking if people want to modify your theme or plugin in a way that differs from how it’s intended to be used, they’re an edge case and they should have to figure out their own solution because they are in the minority.
That said, in the example you provided, I agree it wouldn’t make sense to combine commonly used library scripts. Things that are likely to be used in a lot of other plugins or themes probably should be loaded independently to avoid duplication.
So… basically what I’m saying here is not that I disagree with you but that it depends on the situation. You need to use your judgement as a developer and make decisions that will benefit your users. You won’t always get it right, but the good news is you can always go back and make changes when you screw up. 😉
@rob_neu I see where your coming from and agree. But you also sound like the type of author that when I email and say we have a problem, your likely to put some attention into the issue.
My recent experience has been that not all authors think this way nor really care about their end user as that who is ultimately affected when there is a collision.
Case in point one of my plugins Popup Maker uses Greensock Animation Platform. So does Rev Slider and LayerSlider.
I have had at least 6 complaints from my users and theirs about JS collission issues. They load the entire GSAP library in a custom file and we have no choice but to load it again. Often resulting in broken sliders or popups.
They so far have been unwilling to make any changes. They have updated their code to be more compatible by enclosing functions in their own space, but multiple copies are still loaded.
I always try to respond as quickly as possible whenever a conflict was found. Anyone who isn’t willing to do that, especially on a commercial product, has a whole other set of issues that need to be worked out. LoL
The type of thing you’re talking about crops up quite a bit in WordPress both with front-end libraries and back-end libraries. I think it’s a lot more of a problem with plugins than themes because of the fact that you can only use one theme at a time. It definitely doesn’t make sense to load something like GASP in a concatenated file because it’s so commonly used.
In a situation like that, I think you’re on the money. Either enqueue it normally or at the very least use WordPress to concatenate your scripts and allow them to be unset/removed before that occurs. Jetpack started doing this sort of thing recently and while it is a little bit annoying as a developer, it’s clearly beneficial for users because of vastly improved page load times.
Hey, I think I agree with Rob as theme specific scripts are exempt from this rule. I have started for this reason to create a list of styled and scripts and start to define a standard. https://github.com/grappler/wp-standard-handles
I would love any feedback or PRs.
Hey Ulrich, I will agree to an extent. I completely agree that there needs to be some attempt at standardizing as many as possible. I would say you need to add jQuery cookie, Transit, Greensock AP files etc to your list. Would be happy to do so myself if you grant commit access. user: danieliser
Thanks for the comment.
Great article. We see the effects of developers’ negligence or ignorance or stubbornness in real time on the support threads and on our sites, don’t we?
Anyway, now you have my email. Please hit me up about development.