Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / Javascript

Dynamically Loading a JavaScript File

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
13 Aug 2021CPOL3 min read 37.3K   9   2
A look at different ways to dynamically load JavaScript files after the page is fully loaded
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:

JavaScript
// this is going to be executed when script is loaded
(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
<html>
<head>
</head>
<body>
  <button id="loadButton">Load script file</button>
  <script type="text/javascript">
    document.getElementById('loadButton').onclick = function () {
      // your code goes here
    };
  </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:

JavaScript
document.getElementById("loadButton").onclick = function () {
  var script = document.createElement("script");
  script.src = "remote.js";

  script.onload = function () {
    sayHello("Mohammad");
  };

  // append and execute script
  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:

Image 1

Now, let us refactor the above code and modify it a little bit to be able to use it anywhere else:

JavaScript
/**
 * Used to load and execute javascript file. an be used cross-domain seamlessly.
 * @param file JS file name
 * @param callback Subscribe to get notified when script file is loaded
 **/
function require(file, callback) {
  // create script element

  var script = document.createElement("script");
  script.src = file;

  // monitor script loading
  // IE < 7, does not support onload
  if (callback) {
    script.onreadystatechange = function () {
      if (script.readyState === "loaded" || script.readyState === "complete") {
        // no need to be notified again
        script.onreadystatechange = null;
        // notify user
        callback();
      }
    };

    // other browsers
    script.onload = function () {
      callback();
    };
  }

  // append and execute script
  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:

JavaScript
/**
 * Used to load and execute javascript file. Suffers from same-domain restriction.
 * @param file JS file name
 * @param callback Subscribe to get notified when script file is loaded
 **/
function requireXhr(file, callback) {
  // object initialization
  const xhr = new XMLHttpRequest();

  // subscribe to request events
  xhr.onreadystatechange = function () {
    // readyState:
    // 0 UNSENT Client has been created. open() not called yet.
    // 1 OPENED open() has been called.
    // 2 HEADERS_RECEIVED send() has been called, and headers and status are available.
    // 3 LOADING Downloading; responseText holds partial data.
    // 4 DONE The operation is complete.

    // when not done, return
    if (xhr.readyState !== 4) {
      return;
    }

    // done, check status code
    if (xhr.status !== 200) // 200 = OK
    {
      return;
    }

    // now the file is loaded,
    // go and execute the script
    eval(xhr.responseText);

    // notify caller
    if (callback) {
      callback();
    }
  };

  // open connection to file
  xhr.open("GET", file, true);

  // send the request
  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:

Image 2

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.

Image 3

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:

JavaScript
/**
 * Used to load and execute JavaScript file. 
 * @param file JS file name
 * @param callback Subscribe to get notified when script file is loaded
 **/
 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.

Image 4

The results are great too:

Image 5

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Egypt Egypt
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

Comments and Discussions

 
QuestionRaw XMLHttp Request Pin
Seif Eddine Slimene2-Sep-21 19:46
professionalSeif Eddine Slimene2-Sep-21 19:46 
QuestionThanks Pin
Pete Goodsall17-Aug-21 4:49
Pete Goodsall17-Aug-21 4:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.