UNPKG

@dschz/load-script

Version:

Dynamically load scripts in the browser with caching.

75 lines (74 loc) 2.22 kB
// 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 };