In a previous post we covered what the best way was to include jQuery in WordPress.
In this post, I’m going to talk a little more about the best ways to include Javascipt files.
I’m going to discuss my approach and why I think it’s best.
So, what you might do is to enqueue each supporting scrip then list your custom script, like so:
wp_enqueue_script( 'select2', trailingslashit( get_template_directory_uri() ) . 'select2.js', array( 'jquery' ) );
wp_enqueue_script( 'custom, trailingslashit( get_template_directory_uri() ) . custom.js', array( 'jquery', 'select2') );
It’s important in this scenario that you list the dependant scripts as dependencies, rather then just list them in order. This is to make sure that they are loaded prior to the one who needs it.
For the handles, the custom script should have a prefix; like ‘themename-custom’ or ‘themename-child-custom’ to avoid accidently ending up with the same handle as something else. For example; if two plugins loaded ‘main’ or ‘custom’ you’ll have a problem.
It’s considered best practice that third party scripts use their name as their handle, i.e.’select2′. This is so that if something else is already loading select2, it would not bother loading it twice. Also, loading them twice could course a problem.
By not including the third party scripts in your custom script, it makes that custom script much easier to override.
By sharing scripts you potentally reduce bloat, if several items on the site are using select2 why increase network calls and download sizes by including them again?
That all sounds great right? Yes,v but there is a problem; WordPress’s dependency handling is not that great and the main problem we have is with versions.
Take this scenario. You enclude select2 in your theme. A user installs a plugin that also includes select2. But, they depend on a different version of select2. Dependant on load piorities, the theme or plugin could break. If they use a different handle you could end up loading it twice. Its likely now you’ll create a ‘already defined’ error unless the script has checked for this. If it has then you’re back to the other problem; only one version will load and it may not be the right one.
By enquing our third party scripts, we have introduced a potential point of failure. The dependacy option in the enqueue call is only really used for loading the scripts in the correct order. Also, the version number supplied only really helps you to programmically to check the version number of a script, something you can do in your own code to check a loaded script’s version number, but you can’t make a third party plugin do that too.
When you combine the third party scripts yourself, you control the process and you can be sure that the scripts have been combined in the correct order and that nothing breaks. You’ve tested that the combined file is working before it gets released. With the magic combine scripts button, you don’t really know what’s going to happen.
When combining your scripts, you can isolute them so their functions are only available to your project and are not in the global namespace. This completely removes any fear of conflicts.
Sure, it means you can end up with the same select2 script being loaded in multiple projects accross your site and we all know that you should be DRY. But I think the potental conflict issues are more of a problem.
You should however, always, unless for good reason use the core’s supplied versions of scripts. Like with jQuery, you shouldn’t be suppling your own. You should be looking to make your script compatible with the cores version. The sharing situation there is different, because all plugins and themes that are keeping maintained will be keeping them selves up to date with the version of jQuery suppplied by core.
wp_enqueue_script( 'custom, trailingslashit( get_template_directory_uri() ) . custom.js', array( 'jquery' ) );
What about the ability to override scipts then? Well, yes that is useful and it’s a alot easier
for people to override a enqueued file then one bundled up. But if you package your project correctly and provide the build script to your end users, then a developer will still be able to modify the project and just rebuild it after.
They would be able to unqueue the main project file, build there own from the build script you’ve provided then reload it in their extension plugin or child theme. The build script being the webpack file, gulp file, package.json etc or whatever you used. If you purely just combined files, then even just the unminified version will allow them to modify it.
There is, of course the matter of whether you want your users/clients to be able to override things… That is a different discussion.
We’ve talked mostly about third part scripts thus far; what about your own custom modules that wont be shared by other projects, other then potential extentions? Well the main benefit to listing them seperatly is for any extentions, whether your own or others, the same as with third party scripts.
I often find that when I try to reuse code accross projects, it doesn’t really work out that well. It introduces complexity in the form of compatibility – so I’m not really a fan. When combining and isolating those modules from the glocal namespace, you don’t have to worry about comflicts in the same way as with third party ones.
I think that there is much less reason to not combine than there is with common third party ones. Those doing exentions can build the project as discussed previously. I always build custom modules into one script and very rarely will I enqueue them seperately.
I feel that it’s not a cut and dry issue, so that’s my take on it. I’m interested to hear others thoughts on it.