How to load a script dynamically with Javascript?

About

This page shows you how you can load a script dynamically with Javascript to load and use it when needed.

List

With Pure Javascript

In short, if you add:

Module loading with Script Element insertion

const head = document.querySelector('head');
const scripts = [
	["https://cdnjs.cloudflare.com/ajax/plugins/toolbar/prism-toolbar.js","sha256-kK4/JIYJUKI4Zdg9ZQ7FYyRIqeWPfYKi5QZHO2n/lJI="],
	["https://cdn.example.com/script.js","integrityHash"],
];

scripts.forEach(scriptRow => {
		let script = document.createElement('script');
		script.src=scriptRow[0];
		script.integrity=scriptRow[1];
		script.crossOrigin="anonymous";
		head.append(script);
        script.addEventListener("load", function(){
          console.log("The script has loaded and is usable");
        })
	}
)

For more loader, see the page: Javascript - Module Loader (Script Loader)

Inline script loading with Script Element

let script = document.createElement('script');
script.text="console.log('hello foo');";
document.body.appendChild(script);

Inline script loading with HTML Fragment

Inserting a HTML fragment will not execute any script element.

The solution is that you need:

  • for a src script element (the src attribute has an url):
    • to clone the inserted script element
  • for a inline script element (without an src attribute but with content):
    • to clone the inserted script element
    • or evaluate its content

The below example shows you a clone example. We insert a fragment with insertAdjacent

let htmlFragment = "<script>console.log('hello world');<\/script>";
// we have escape the closing script ie <\/script> because this code run in a script element
document.body.insertAdjacentHTML('afterbegin', htmlFragment);
  • and we can see that there is no console output, the code was not executed

But when we clone and insert it as element, it will be:

  • The clone function
let cloneScriptElement = function(element){
   let clone = document.createElement(element.localName);
   clone.text = element.text
   Array.from(element.attributes).forEach( attr => clone.setAttribute(attr.name, attr.value) );
   return clone;
}
  • The replacement
let script = document.body.querySelector("script"); // the first node after the body
let clone = cloneScriptElement(script );
script.parentNode.replaceChild(clone, script);
  • The console has now an output.

Via the import statement

Via a dynamic import statement.

Example:

import('https://cdn.jsdelivr.net/npm/[email protected]/dist/moment.js').then( ({ default: moment}) => {
    const now = moment().format();
    console.log(`The actual time is "${now}"`);
});

Via Browser Module Loader

browser module loader are libraries that manage the loading of modules and their dependencies.

Example with RequireJs

In this example, we will load the bowser UMD library in order to get information about your browser.

  • Adding the require library in your HTML page
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
require(['https://cdnjs.cloudflare.com/ajax/libs/bowser/2.11.0/bundled.min.js'], function(bowser) {
   const browser = bowser.getParser(window.navigator.userAgent);
   console.log(`Your browser name is "${browser.getBrowserName()}"`);
});
  • Output:

Via workers

It's also possible to offload the loading of scripts to workers.

Example: https://partytown.builder.io/