
Minimizing asset loading time and increasing performance of a website is a web-developer’s first priority. These days most websites depend heavily on several JavaSript and CSS files including third-party ones. You can add all of them in your head
tag (or at the end of body
). Or you can lazy-load them later depending on certain conditions.
Why conditionally load resources
Loading all JavaScript files at once can drop site performance significantly. Needless to say, if your site is slow, users will stay long enough to finish loading. There is yet another reason why you may want to load JavaScript at a later stage: You may not need all the javascript for every user. Depending on the browser, location and device among many other factors, there can be separate file for each case. Performing the tests and loading libraries depending on the result is the right thing to do in such cases.
Why not use deferred
JavaScript used to provide a deferred
attribute to load files at a later stage. But the method has been deprecated and replaced by Promise
class. Besides, this method did not let you load files depending on a certain condition — it just loaded them later.
How to load libraries based on conditions
There are several things you can do to load JavaScript (and CSS stylesheets for that matter) depending on certain conditions. Here I am going to discuss two methods.
1. Using vanilla JavaScript
You can perform a certain check with vanilla JS. And then, depending on the result, you can create a script
tag (inside head
may be) and set the src
attribute to the url of the source file.
For example, let us say you want to load separate resources for desktop users and for mobile users. You can use this:
var script = document.createElement("script"); script.type = "text/javascript"; if (window.matchMedia("(max-width: 568px)").matches) { script.src = "//path/to/mobile-users.js"; } else { script.src = "//path/to/desktop-users.js"; } document.body.appendChild(script);
The above code creates a script
tag and performs a test with window.matchMedia
. If the results show that the user is on a mobile device (max-width is 568px, e.g.), then set the source of the script tag to the javascript file intended for mobile-users. Otherwise, set it to desktop-users.js. Finally, it appends the script
tag to the end of body
. You can use similar logic for CSS stylesheets (create a <link>
tag, set rel
to stylesheet
, etc.)
2. Using jQuery
However outdated you may tag jQuery, it is still widely used. Using jQuery, you can achieve the same conditional resource loading, with less amount of code. jQuery provides a getScript
method to load JavaScript files and execute them. For instance, you may have:
if (window.matchMedia("(max-width: 568px)").matches) { $.getScript("//path/to/mobile-users.js"); } else { $.getScript("//path/to/desktop-users.js"); }
This is a lot less amount of code but it is useless if you want to conditionally load CSS stylesheets.
3. Carl.js
Carl.js, short for Conditional Asset Resource Loader, is a tiny yet useful JavaScript library that lets you load CSS, JavaScript and even HTML files, depending on test results. Carl.js can be used by simply writing a resources.json
file. The syntax is dead simple — for each condition, write a test
and an array
of resources to load if the test passes. It is something like this:
{ "form.login-form": [ "/path/to/login-form-styles.css", "/path/to/login-logic.js" ] }
The above code will load a JavaScript and a CSS file only on form
tags which has a class login-form
. Carl.js is very useful on large projects where you want to organize individual resources. Indirectly, it forces you to break web-pages into small and reusable components.
Conclusion
Resource-heavy web-pages need more care when it comes to delivering JavaScript libraries and CSS stylesheets. In order to ensure optimal page-speed without sacrificing user-experience, conditional resource delivery is more beneficial than monolithic html structure. I personally prefer using Carl.js over the other two methods I described above. This is mostly because I forces me to write reusable components. Plus, it is more convenient to manage the resources from one single file.