Dynamic loading of JavaScript files is one of the very useful tools that you must have in your set. It allows you to optimize web page performance by moving blocking scripts off the loading process (usually they call this “lazy loading”), and to load scripts only when the user needs them (usually they call this “on-demand loading”.) This tool will greatly improve your page performance if you use it wisely.
Setting Up
Let us define our example model, we will start by defining the remote file that needs to be dynamically loaded. Here’s the definition for “remote.js” file:
(function () {
console.log("Remote script loaded");
}());
var sayHello = function (name) {
alert("Hello", name);
}
In the above code, we define an immediate function to track file loading. We also define a custom function to be called from our main page.
Now, here is our main “index.htm” page. It contains only a single button that will be used to load and test the file.
<html>
<head>
</head>
<body>
<button id="loadButton">Load script file</button>
<script type="text/javascript">
document.getElementById('loadButton').onclick = function () {
};
</script>
</body>
</html>
The No-Brainer Way!
The most straightforward way to load a JavaScript file is to reference it in a <script>
element. The easiest way to dynamically load this file is to dynamically load this element! (You didn’t see that coming? Did you?)
Let us update the code and see results in action:
document.getElementById("loadButton").onclick = function () {
var script = document.createElement("script");
script.src = "remote.js";
script.onload = function () {
sayHello("Mohammad");
};
document.documentElement.firstChild.appendChild(script);
};
The above code simply creates a <script>
element and sets the src
field of this element to the path of our file. Then it uses the appendChild()
function to append it to the first child of our code, the <head>
element. The following code results in the following:
Now, let us refactor the above code and modify it a little bit to be able to use it anywhere else:
function require(file, callback) {
var script = document.createElement("script");
script.src = file;
if (callback) {
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
callback();
}
};
script.onload = function () {
callback();
};
}
document.documentElement.firstChild.appendChild(script);
}
document.getElementById("loadButton").onclick = function () {
require("remote.js", function () {
sayHello("Mohammad");
});
};
Now you can easily call require()
along with JavaScript path and a callback function to be notified when the script is loaded.
The Backbreaking Way!
Another way to dynamically load a JavaScript file is to retrieve it using a classic HTTP request. This is a pure JavaScript call, and yet it has many drawbacks. Let us see it in action:
function requireXhr(file, callback) {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status !== 200)
{
return;
}
eval(xhr.responseText);
if (callback) {
callback();
}
};
xhr.open("GET", file, true);
xhr.send();
}
document.getElementById("loadButton").onclick = function () {
requireXhr("remote.js", function () {
sayHello("Mohammad");
});
};
The code is very simple and self-descriptive. We set-up an HTML request using XMLHttpRequest
object, and we fire it. Then, we monitor its status changes and perform accordingly.
When we execute above code, we get the following results. We can see our successful XHR request in the DevTools extension:
On the other hand, the results were disappointing. We were able to run the script successfully and there is no clue of the script file in the HTML content, however, due to the private scope of eval()
, we are not able to call the loaded functions.
Other drawbacks of this way that it suffers a lot when working cross-domain. And you cannot load from a local path too!
A Piece of Cake!
Now comes the most straightforward way to lazy-load a JavaScript file, the jQuery way. jQuery provides a function called getScript()
(which is a shorthand of ajax()
) to retrieve and load JavaScript files. Here is the code:
function requireAjax(file, callback) {
jQuery.getScript(file, callback);
}
document.getElementById("loadButton").onclick = function () {
requireAjax("remote.js", function () {
sayHello("Mohammad");
});
};
Although jQuery.getScript()
uses XMLHttpRequest
internally, and you can see the request in XHR list in DevTools, it does not suffer from the same drawbacks (like same-domain restriction) as XMLHttpRequest
. It's easier to use and to perform than the raw XMLHttpRequest
.
The results are great too:
Conclusion
To conclude, if you have jQuery enabled in your page, you can easily use jQuery.getScript()
to load a JavaScript asynchronously on-demand. If you are looking for a pure JavaScript approach, go for the <script>
method, which has the little overhead incurred.
Source Code
The example is available on GitHub on the following location:
Thank You!
Thanks for reading. I hope you have enjoyed reading this! 😊
History
- 13th August, 2021: Initial version
Mohammad Elsheimy is a developer, trainer, and technical writer currently hired by one of the leading fintech companies in Middle East, as a technical lead.
Mohammad is a MCP, MCTS, MCPD, MCSA, MCSE, and MCT expertized in Microsoft technologies, data management, analytics, Azure and DevOps solutions. He is also a Project Management Professional (PMP) and a Quranic Readings college (Al-Azhar) graduate specialized in Quranic readings, Islamic legislation, and the Arabic language.
Mohammad was born in Egypt. He loves his machine and his code more than anything else!
Currently, Mohammad runs two blogs: "Just Like [a] Magic" (http://JustLikeAMagic.com) and "مع الدوت نت" (http://WithdDotNet.net), both dedicated for programming and Microsoft technologies.
You can reach Mohammad at elsheimy[at]live[dot]com