Skip to main content
Guides

Key Concepts

useScript() is the base API. Registry and global scripts build on it for common loading patterns:

  1. Registry Scripts: Preconfigured third-party scripts that load through Nuxt config, composables, and components.
  2. Global Scripts: Scripts loaded through your Nuxt config file.

Unhead abstraction

Nuxt Scripts wraps Unhead's useScript(), which builds on useHead(). Script attributes supported by useHead are therefore available through Nuxt Scripts too.

Script singleton

Nuxt Scripts deduplicates calls with the same src (or key) because scripts load globally and all components share them.

The first call initializes the script. Later calls with the same identity return that instance.

Wrap a repeated call in a composable so every component uses the same configuration:

useMyScript.ts
export function useMyScript() {
  return useScript({
    src: 'https://example.com/script.js',
  })
}

Default behavior

By default, Nuxt Scripts leaves script tags out of the SSR response and loads them on the client with the onNuxtReady trigger. This keeps third-party code out of hydration.

You can change this behavior by modifying the defaultScriptOptions.

Nuxt Scripts also applies several privacy and performance defaults to cross-origin script elements:

  • crossorigin="anonymous": Prevents the script request from sending cross-origin credentials, including cookies.
  • referrerpolicy="no-referrer": Prevents sharing the page URL with third-party servers.

When you enable warmup, <link> hints use fetchpriority="low" to avoid competing with critical resources.

Understanding proxied functions

useScript() can return functions before the browser has loaded their script:

const { proxy } = useScript('/script.js', {
  use: () => ({ gtag: (window as any).gtag }),
})
proxy.gtag('event', 'page_view')

The proxy queues the gtag call and replays it after the script loads. If the script never loads, the call never runs.

This is useful when:

  • the same code runs during SSR;
  • an ad blocker may prevent the script from loading; or
  • your application may call the API before the request finishes.

Proxy calls have two tradeoffs:

  • Proxy calls return undefined. Use load() or onLoaded() when you need a function's return value.
  • A queued call can be harder to trace because it runs later, after the script becomes available.

Await the load when you need the script API directly:

const { onLoaded } = useScript('/script.js', {
  use: () => ({ gtag: (window as any).gtag }),
})
// use the script instance directly, not proxied
onLoaded(({ gtag }) => {
  gtag('event', 'page_view')
})