@dschz/load-script
Version:
Dynamically load scripts in the browser with caching.
75 lines (74 loc) • 2.22 kB
JavaScript
// src/loadScript.ts
var SCRIPT_CACHE = /* @__PURE__ */ new Map();
var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
var loadScript = async (src, options = {}, container) => {
const {
id,
async = true,
defer = false,
noModule = false,
textContent = null,
fetchPriority = "auto",
type = "text/javascript",
innerHTML,
crossOrigin,
referrerPolicy,
integrity,
nonce,
onLoad,
onError,
...attributes
} = options;
if (!isBrowser()) {
const error = new Error("loadScript can only be used in the browser");
error.name = "NotBrowserEnvironmentError";
return Promise.reject(error);
}
if (!src) {
const error = new Error('No "src" provided to loadScript');
error.name = "NoSrcProvidedError";
return Promise.reject(error);
}
const cacheable = !innerHTML && !textContent;
if (cacheable) {
const existingTag = document.querySelector(`script[src="${src}"]`);
if (SCRIPT_CACHE.has(src)) {
if (document.contains(existingTag)) return SCRIPT_CACHE.get(src);
SCRIPT_CACHE.delete(src);
}
if (existingTag) return Promise.resolve(existingTag);
}
const promise = new Promise((resolve, reject) => {
const script = document.createElement("script");
(container ?? document.head).appendChild(script);
script.src = src;
script.type = type;
script.fetchPriority = fetchPriority;
script.async = async;
script.defer = defer;
script.noModule = noModule;
script.textContent = textContent;
if (id) script.id = id;
if (innerHTML) script.innerHTML = innerHTML;
if (crossOrigin) script.crossOrigin = crossOrigin;
if (referrerPolicy) script.referrerPolicy = referrerPolicy;
if (integrity) script.integrity = integrity;
if (nonce) script.nonce = nonce;
script.onload = (e) => {
onLoad?.(e);
resolve(script);
};
script.onerror = (e) => {
onError?.(e);
reject(e);
};
Object.entries(attributes).forEach(([key, value]) => {
script.setAttribute(key, String(value));
});
});
if (cacheable) SCRIPT_CACHE.set(src, promise);
return promise;
};
export {
loadScript
};