Dynamic Library Loading

Dynamic library loading functionality for BetterForms - Load external JavaScript libraries, ESM modules, and CSS files from CDN dynamically within function actions.

Version: 3.3.1+ Feature: BF.libraryLoadOnce(), BF.libraryIsLoaded(), BF.libraryGetLoaded()

Overview

Load external JavaScript libraries, ESM modules, and CSS files from CDN dynamically within your function actions. Libraries are loaded once and cached automatically (idempotent), with built-in XSS protection and race condition prevention.

Why Use This?

  • Reduce initial page load - Only load libraries when needed

  • Self-contained components - Components can load their own dependencies

  • Version flexibility - Use different library versions per form

  • No rebuild required - Add new libraries without webpack rebuild

Quick Start

Load a UMD Library

// Load PapaParse from CDN
await BF.libraryLoadOnce('https://cdn.jsdelivr.net/npm/[email protected]/papaparse.min.js');

// Use it immediately
const result = Papa.parse('Name,Age\nJohn,30', { header: true });
console.log(result.data); // [{Name: "John", Age: "30"}]

Load an ESM Module

ESM modules are scoped to the current function action. See "ESM Module Scope" section below for multi-action usage patterns.

Load CSS


API Reference

BF.libraryLoadOnce(url, options)

Load a library from CDN. Returns immediately if already loaded (idempotent).

Parameters:

Parameter
Type
Default
Description

url

String

required

CDN URL to JavaScript, ESM module, or CSS file

options

Object

{}

Optional configuration

options.type

String

'script'

'script' or 'stylesheet'

options.moduleType

String

'classic'

'classic' for UMD or 'module' for ESM

options.timeout

Number

30000

Timeout in milliseconds

options.attributes

Object

{}

Additional HTML attributes (e.g., integrity, crossorigin)

Returns:

  • UMD/Script: Promise resolving to { url, type, element, cached }

  • ESM Module: Promise resolving to the module object

Throws: Error if network failure, timeout, or invalid parameters


BF.libraryIsLoaded(url)

Check if a library is already loaded.

Returns: Boolean


BF.libraryGetLoaded()

Get array of all loaded library URLs.

Returns: Array of URL strings


Usage Examples

Example 1: Chart.js

Example 2: DayJS (ESM)

Example 3: Axios for API Calls

Example 4: Load with Security (SRI)

Example 5: Error Handling

Example 6: Multiple Libraries

Example 7: Dynamic Library Selection


ESM Module Scope

UMD vs ESM Behavior

UMD Libraries (automatically global):

ESM Modules (function-scoped):

The library is cached, so re-loading is < 1ms:

When to use:

  • βœ… Most common case

  • βœ… Clean, simple code

  • βœ… Nearly instant (cached)

Solution 2: Bind to Window (If Needed Globally)

Manually store the module on window for global access:

When to use:

  • Used across many actions

  • Need consistent reference

  • Don't mind global namespace

Do You Even Need It Again?

In many cases, you won't need the module after initial setup:

Only need multi-action access if:

  • Calling library functions repeatedly

  • Building complex multi-step workflows

  • Library maintains state you need to access


Best Practices

βœ… DO:

  • Use version pinning: Specify exact versions in CDN URLs

  • Idempotent by design: No need to check before loading

  • Use error handling: Always catch potential failures

  • Prefer UMD builds: More compatible, simpler to use

❌ DON'T:

  • Don't load untrusted CDNs: Security risk

  • Don't load without error handling: Can break your form

  • Don't use latest/unstable versions: Use pinned versions

  • Don't load duplicate libraries: Check first with BF.libraryIsLoaded()


Supported Library Formats

βœ… UMD (Universal Module Definition)

  • Most common format

  • Exposes global variable

  • Works everywhere

  • Examples: Chart.js, PapaParse, QRCode, Axios

βœ… ESM (ES Modules)

  • Modern format

  • Uses import/export

  • Returns module object

  • Examples: DayJS, D3.js, Lit (web components)

βœ… CSS Stylesheets

  • Any CSS file

  • Animations, themes, frameworks

  • Examples: Animate.css, Font Awesome


Finding CDN URLs

Finding the correct CDN URL can be tricky. Here's how:

Step 1: Find the Package on npm

  1. Go to https://www.npmjs.com/package/package-name

  2. Check for version number and main file info

Step 2: Browse the CDN

jsDelivr (Recommended)

  • Browse: https://cdn.jsdelivr.net/npm/package-name@version/

  • Example: https://cdn.jsdelivr.net/npm/[email protected]/

  • Look in: dist/, build/, or root folder

  • ESM shortcut: Add /+esm to auto-find ESM entry

Common file patterns:

  • package.min.js - Minified UMD (most common)

  • package.umd.js - UMD build

  • dist/package.js - Main distribution file

  • build/package.min.js - Built file

unpkg

  • Browse: https://unpkg.com/package@version/?meta (add ?meta)

  • Example: https://unpkg.com/[email protected]/?meta

cdnjs

  • Search: https://cdnjs.com/libraries/package-name

  • Example: https://cdnjs.com/libraries/Chart.js

Step 3: Verify the File Works

Test in browser console first:

Troubleshooting 404 Errors

  1. Check version exists: Verify on npmjs.com

  2. Try alternate paths:

    • package.min.js

    • dist/package.min.js

    • build/package.min.js

    • index.js

  3. Check package.json: https://cdn.jsdelivr.net/npm/package@version/package.json

    • Look for "main", "browser", or "module" fields

Real Examples

Chart.js:

  1. Browse: https://cdn.jsdelivr.net/npm/[email protected]/

  2. Find: dist/chart.umd.js

  3. URL: https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.js

PapaParse:

  1. Browse: https://cdn.jsdelivr.net/npm/[email protected]/

  2. Find: papaparse.min.js (at root)

  3. URL: https://cdn.jsdelivr.net/npm/[email protected]/papaparse.min.js

DayJS ESM:

  1. Use shortcut: https://cdn.jsdelivr.net/npm/[email protected]/+esm

  2. Done! (jsDelivr finds ESM automatically)


Common Libraries

Chart.js (Charting)

PapaParse (CSV Parser)

QRCode (QR Generator)

Axios (HTTP Client)

DayJS (ESM - Date Library)

Sortable.js (Drag & Drop)


Troubleshooting

Library Not Available After Loading

Problem: Library loads but window.LibraryName is undefined

Solution: You might have loaded an ESM module as UMD

Timeout Error

Problem: Library takes too long to load

Solution: Increase timeout or check network

CORS Error

Problem: "blocked by CORS policy"

Solution: Use a reputable CDN that supports CORS (jsDelivr, unpkg, cdnjs)

Version Conflicts

Problem: Library already loaded but different version

Solution: Check what's loaded first


Need Help?


Happy coding! πŸš€

Last updated