@dschz/load-script
Version:
Dynamically load scripts in the browser with caching.
70 lines (67 loc) • 3.51 kB
TypeScript
type Blocking = "render" | "media" | "document" | (string & {});
type CrossOrigin = "anonymous" | "use-credentials" | "";
type FetchPriority = "auto" | "high" | "low";
type ReferrerPolicy = "" | "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" | "unsafe-url";
type ScriptType = "text/javascript" | "module" | "application/ld+json" | "importmap" | "text/json" | "";
/**
* Options for loading a script.
*
* @see {@link loadScript}
*/
type LoadScriptOptions = {
/** Optional ID for DOM targeting or deduplication */
readonly id?: string;
/** Whether the script should execute asynchronously (default: `true`) */
readonly async?: boolean;
/** Whether the script should defer execution until after the document has parsed (default: `false`) */
readonly defer?: boolean;
/** Prevents the script from being executed in modules if true (default: `false`) */
readonly noModule?: boolean;
/** Subresource integrity hash for verifying the fetched script */
readonly integrity?: string;
/** CSP nonce for allowing script execution under Content-Security-Policy */
readonly nonce?: string;
/** Experimental: Instructs browser blocking behavior (e.g. "render") */
readonly blocking?: Blocking;
/** The MIME type of the script (default: `"text/javascript"`) */
readonly type?: ScriptType;
/** Specifies the referrer policy for fetching the script */
readonly referrerPolicy?: ReferrerPolicy;
/** Indicates the relative fetch priority of the script */
readonly fetchPriority?: FetchPriority;
/** Indicates whether to send a cross-origin request and how to handle it */
readonly crossOrigin?: CrossOrigin;
/**
* Content to be inserted into the script as raw HTML (use with caution)
*
* Prefer using `textContent` over `innerHTML` to avoid security risks and maintain CSP compatibility.
*/
readonly innerHTML?: string;
/** Plain text content to be inserted into the script */
readonly textContent?: string | null;
/** Any additional data-* attributes to apply to the script element */
readonly [key: `data-${string}`]: string | boolean | undefined;
/** Called when the script successfully loads */
readonly onLoad?: (e: Event) => void;
/** Called when the script fails to load or errors */
readonly onError?: (e: string | Event) => void;
};
/**
* Loads a script into the DOM and returns a Promise that resolves to the HTMLScriptElement.
* This is a low-level API that gives you full control over when and where the script is appended.
*
* This method is safe against duplicate script injection — it caches by `src` and avoids injecting the same script twice.
* If the script already exists in the DOM, it resolves immediately with the existing element.
*
* @example
* ```ts
* const script = await loadScript("https://example.com/library.js", { type: "module" }, document.head);
* ```
*
* @param src - The script URL to load.
* @param options - additional options for the script (e.g. async, type, textContent).
* @param container - Optional DOM element to append the script to (defaults to `document.head`).
* @returns A Promise that resolves to the script element.
*/
declare const loadScript: (src: string, options?: LoadScriptOptions, container?: HTMLElement | null) => Promise<HTMLScriptElement>;
export { type LoadScriptOptions, loadScript };