A lightweight library for dynamically loading any web resource through one unified Promise-based API — scripts, stylesheets, JSON, fonts, images, audio, video, and binary files.
Loading resources programmatically in the browser is surprisingly messy. The platform gives you several different mechanisms depending on resource type — each with its own quirks around load events, error handling, and caching:
// A script
const s = document.createElement('script');
s.src = url; s.onload = resolve; s.onerror = reject;
document.head.appendChild(s);
// A stylesheet
const l = document.createElement('link');
l.rel = 'stylesheet'; l.href = url;
document.head.appendChild(l);
// JSON data
const data = await fetch(url).then(r => r.json());
// A font
const font = new FontFace('MyFont', `url(${url})`);
await font.load();
document.fonts.add(font);
Then add retries, timeouts, deduplication, and concurrency limits. You're writing the same boilerplate on every project. ResourceLoader.js solves all of it with one call:
await ResourceLoader.include([
'https://example.com/app.css',
'https://example.com/app.js',
'https://api.example.com/config.json',
]);
// All three loaded. Start your app.
Transient failures are handled automatically. Configure retries, delay between attempts, and a per-attempt timeout — each retry gets its own fresh clock.
ResourceLoader.include([url], {
retries: 3,
retryDelay: 2000,
timeout: 5000,
});
Limit simultaneous loads to avoid saturating the browser's connection pool. When queue slots are limited, higher-priority resources load first.
// Critical font loads first
ResourceLoader.include([font], { priority: 10 });
ResourceLoader.include([img], {
priority: 1,
maxConcurrency: 4,
});
An internal registry tracks every URL. Requesting something already loaded or loading returns the existing Promise — no duplicate network requests, ever.
ResourceLoader.getResourceState('app.js');
// → 'loading' | 'loaded' | 'unloaded'
Every failure surfaces as a typed error object so you always know exactly what went wrong and why — not an opaque DOM event or a raw network rejection.
try {
await ResourceLoader.include([urls]);
} catch (err) {
// err.type: 'network' | 'timeout'
// | 'abort' | 'unsupported'
// err.results — per-URL breakdown
}
Extension detection picks the right loading mechanism automatically. No configuration needed.
| Category | Extensions | Loaded via |
|---|---|---|
| Scripts | .js |
<script> element |
| Stylesheets | .css |
<link> element |
| JSON data | .json |
fetch() + response.json() |
| Images | .jpg .png .gif .svg .webp |
<img> element |
| Fonts | .woff .woff2 |
FontFace API |
| Audio | .mp3 .ogg .wav |
fetch() + response.blob() |
| Video | .mp4 .avi .webm |
fetch() + response.blob() |
| Binary / PDF | .pdf .zip .bin |
fetch() + response.blob() |
The entire public API. After inclusion, everything lives on window.ResourceLoader.
| Method | Description |
|---|---|
include(urls, opts?) |
Load one or more resources. Returns a Promise that resolves when all succeed or rejects with a structured aggregate error. |
getResourceState(url) |
Returns 'loading', 'loaded', or 'unloaded'.
|
cancelResource(url) |
Abort an in-flight load. |
cancelAll() |
Abort all pending loads at once. |
unloadResource(url) |
Remove a loaded resource from the DOM and clear it from the state registry. |
setLoggingLevel(level) |
Set global log verbosity: 'silent', 'warn', or
'verbose'. |
Pass an options object as the second argument to
include().
| Option | Default | Description |
|---|---|---|
retries |
0 |
Number of additional attempts after a network or timeout
failure. |
retryDelay |
0 |
Milliseconds to wait between retry attempts. |
timeout |
0 |
Per-attempt timeout in ms. 0 means no limit. |
maxConcurrency |
3 |
Maximum simultaneous loads. |
priority |
0 |
Queue priority — higher numbers load first when slots are limited. |
cacheBusting |
false |
Append a timestamp query string to prevent stale cache hits. |
cacheBustingTypes |
['js','css'] |
Which extensions to apply cache-busting to. |
restrictCacheBustingToLocal |
true |
Only bust same-origin URLs. |
onSuccess |
— | Callback fired for each successful load: (data, url) => void. |
onError |
— | Callback fired for each failure: (error, url) => void. |
logLevel |
'warn' |
'silent', 'warn', or 'verbose'. |
No bundler required. Pick the delivery method that fits your workflow.
<script src="https://cdn.jsdelivr.net/npm/resourceloader-js@1.0.2/resourceLoader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/resourceloader-js/resourceLoader.js"></script>
<script src="https://unpkg.com/resourceloader-js/resourceLoader.js"></script>
npm install resourceloader-js
// CommonJS
const ResourceLoader = require('resourceloader-js');
// ESM
import ResourceLoader from 'resourceloader-js';
After inclusion the library is available as window.ResourceLoader in browser
environments.
It is not designed for server-side use — it targets browser APIs (document,
FontFace, fetch, DOM elements).
Everything running together — parallel loads, retries, callbacks, and error handling.
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/resourceloader-js/resourceLoader.js"></script>
</head>
<body>
<script>
ResourceLoader.include([
'https://cdn.example.com/theme.css',
'https://cdn.example.com/vendor.js',
'https://api.example.com/config.json',
], {
retries: 2,
timeout: 8000,
logLevel: 'verbose',
onSuccess: (data, url) => console.log('Ready:', url),
onError: (err, url) => console.warn('Failed:', url, err.message),
})
.then(() => {
initApp(); // all resources ready
})
.catch((err) => {
console.error('Load failed:', err);
});
</script>
</body>
</html>