Skip to main content

Overview

The loadScript function dynamically loads external JavaScript files into the HTML document. It provides control over loading strategies (defer/async), prevents duplicate script loading, and supports callbacks for post-load execution.

Location

source/js/modules/_loadScript.js

Function Signature

loadScript(src, loading = "defer", callback, callbackForced = false)

Parameters

src
string
required
The URL of the script to load. Can be:
  • Full URL with protocol: https://example.com/script.js
  • Protocol-relative URL: //example.com/script.js
  • Domain-only URL: example.com/script.js (auto-prepended with https://)
loading
string
default:"defer"
The loading strategy for the script:
  • "defer" - Script executes after HTML parsing completes
  • "async" - Script executes as soon as it’s available
callback
function
Optional callback function to execute when the script finishes loading.
callbackForced
boolean
default:"false"
If true, executes the callback even when the script is already loaded (skipped duplicate).

Returns

Type: void This function does not return any value.

Implementation Details

URL Normalization

The function automatically normalizes URLs to use HTTPS:
if (!src.startsWith("http") && !src.startsWith("https")) {
  src = (src.startsWith("//")) ? `https:${src}` : `https://${src}`;
}

Duplicate Prevention

Before loading, the function checks if a script with the same source already exists:
if (document.querySelector(`script[src="${src}"]`)) {
  if (callback && callbackForced) callback();
  return;
}

Script Element Creation

The function creates a script element with appropriate attributes:
const script = document.createElement("script");
script.src = src;
script.crossOrigin = "anonymous";

if (loading === "defer") script.defer = true;
if (loading === "async") script.async = true;

Usage Examples

Basic Script Loading (Deferred)

import loadScript from './modules/_loadScript';

// Load with default defer strategy
loadScript('https://cdn.example.com/library.js');

Async Loading with Callback

loadScript(
  'https://cdn.example.com/maps.js',
  'async',
  () => {
    console.log('Maps library loaded!');
    initializeMap();
  }
);

Protocol-Relative URL

// Automatically converts to https://
loadScript('//cdn.jsdelivr.net/npm/[email protected]/dist/lib.min.js');

Real-World Example (from main.js)

Loading balance-text for Safari browsers:
if (navigator.userAgent.indexOf('Safari') != -1 && 
    navigator.userAgent.indexOf('Chrome') == -1) {
  loadScript(
    '//cdn.jsdelivr.net/npm/[email protected]/balancetext.min.js',
    'async',
    () => {
      balanceText(document.querySelectorAll('[x-balance-text]'), {watch: true});
    }
  );
}

Using in Alpine.data Components

The loadScript function is available in the xDOM component:
<div x-data="xDOM">
  <button @click="loadScript('https://example.com/widget.js', 'async', () => alert('Loaded!'))">
    Load Widget
  </button>
</div>

Loading Strategies

Defer vs Async

// Defer: Executes after HTML parsing, maintains order
loadScript('script1.js', 'defer');
loadScript('script2.js', 'defer');
// script1.js will execute before script2.js

Callback Behavior

Standard Callback

Callback executes only when the script is freshly loaded:
loadScript('lib.js', 'defer', () => {
  console.log('Script loaded for the first time');
});

// Second call - callback won't execute
loadScript('lib.js', 'defer', () => {
  console.log('This will NOT run');
});

Forced Callback

Callback executes even if script was already loaded:
loadScript('lib.js', 'defer', () => {
  console.log('First load');
});

// Second call - callback WILL execute
loadScript('lib.js', 'defer', () => {
  console.log('This WILL run even though script exists');
}, true); // callbackForced = true

Best Practices

  • Use defer for scripts that depend on DOM content
  • Use async for independent scripts (analytics, ads)
  • Always provide callbacks for scripts that require initialization
  • Use protocol-relative URLs (//) to match the page protocol
  • Callbacks may not fire if script loading fails
  • Multiple calls with same URL won’t reload the script
  • Set callbackForced=true if you need callback execution on duplicate loads

Security

All dynamically loaded scripts include the crossOrigin="anonymous" attribute for CORS compliance.

Build docs developers (and LLMs) love