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>