Skip to main content

useScript Deep Dive

The useScript hook is a universal tool for managing script injection in Archibald applications. It supports multiple loading strategies, SSR integration, and experimental features like Partytown.


Loading Strategies

The strategy parameter determines when and how the script is injected into the document.

afterInteractive (Default)

The script is injected on the client-side after the page has become interactive. It uses a MutationObserver to wait for hydration to complete before injection.

beforeHydration

The script is injected on the server-side during the initial render pass. It will be present in the HTML sent to the client, ensuring it runs as early as possible.

worker

Experimental strategy that leverages Partytown to run scripts in a Web Worker, offloading them from the main thread.


SSR & Hydration

useScript handles the transition between server-side rendering and client-side hydration.

  • Server-Side: If strategy: 'beforeHydration' is used, the script is added to the HeadContext and rendered in the <head> as part of the initial HTML.
  • Client-Side: For afterInteractive, the hook waits for the document.body to stabilize using a MutationObserver. Once stabilized, the script is injected into the <body>. This prevents hydration mismatches and ensures scripts don't interfere with the initial React mount.

Suspense Integration

If suspense: true is provided (or enabled globally via DataClient), useScript will throw a Promise while the script is loading. This allows you to catch the loading state using a standard React Suspense boundary.

<Suspense fallback={<p>Loading analytics...</p>}>
<AnalyticsComponent />
</Suspense>

// Inside AnalyticsComponent:
useScript({
id: 'analytics',
src: 'https://example.com/script.js',
suspense: true
});

Partytown (Worker Strategy)

To use the worker strategy, you must have Partytown initialized in your application and enabled in the Archibald configuration:

// archibald.config.ts
export default {
experimental: {
partytown: true
}
}

The hook will verify that window.partytown is available before attempting to load the script.


How it Works Step-by-Step

Scenario: strategy: 'afterInteractive'

  1. Component Mounts: The hook initializes and sets up a MutationObserver on document.body.
  2. Hydration Check: The hook waits for the DOM to settle (monitored via observeHydrationChanges).
  3. Script Check: The hook checks if a script with the same id already exists in the document to prevent duplicates.
  4. Injection: A new <script> element is created and injected into the <body>.
  5. State Update: If using Suspense, a DecoratedPromise is created and "thrown" to the nearest boundary.
  6. Load/Error Events: The hook listens for the native load and error events of the script element and triggers the corresponding callbacks (onLoad, onError).
  7. Cleanup: When the component unmounts, the MutationObserver is disconnected, but the script remains in the document (unless manually removed via Script API).

Scenario: strategy: 'beforeHydration'

  1. Server Rendering: The hook detects it's running on the server.
  2. Context Injection: The script content is generated and added to the HeadManager.
  3. HTML Generation: The script is rendered into the <head> as part of the initial server response (via {{ page.tags }}).
  4. Client Hydration: The hook runs on the client but detects the script already exists via its id and skips re-injection.