Guides

Key Concepts

The useScript() composable is the core of Nuxt Scripts and loads all scripts.

Nuxt Scripts provides additional layers of abstraction built on top of useScript() to make it easier to load scripts in different ways.

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

Unhead Abstraction

The Nuxt Scripts useScript() composable is an abstraction of Unhead's useScript(), which in turn is an abstraction on top of useHead. Many of the features available to you through useHead are also available in Nuxt Scripts useScript().

Script Singleton

With Nuxt Scripts, you cannot load a script with the same src (or key) multiple times because the script loads globally and all components share it.

This means that a script will only go through the initialization process once, and any subsequent calls to useScript() will return the same instance.

For this reason, you may consider wrapping your useScript() calls in their own composable to allow for easier instantiation.

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

Default Behavior

Nuxt Scripts does not insert script tags within the SSR response. This performance decision minimizes interruptions to the hydration process. Instead, Nuxt loads scripts by default when fully hydrated on the client side.

You can change this behavior by modifying the defaultScriptOptions.

Nuxt Scripts also inserts several extra tags to the <script> element to optimize performance and privacy.

  • async - Nuxt loads scripts asynchronously to prevent blocking page rendering.
  • defer - Nuxt defers scripts to ensure they execute in their loading order.
  • crossorigin="anonymous" - Nuxt loads scripts with the anonymous attribute to prevent cookie access.
  • referrerpolicy="no-referrer" - Nuxt uses the no-referrer policy to prevent sending the referrer header.
  • fetchpriority="low" - Nuxt loads scripts with lower priority to improve performance.

Note: async does not apply by default because the module uses defer. If you need async, you can explicitly disable defer.

Understanding proxied functions

You may wonder how the useScript() composable can return SSR safe functions that you can call before the script loads.

const { proxy } = useScript('/script.js')
// just works as you'd expect - magic?
proxy.gtag('event', 'page_view')

The gtag function call is a proxy that queues the function to call when the script loads. If the script never loads then the function never executes.

This has several benefits:

  • SSR safe
  • Won't break your site if the script never loads (blocked by adblockers)
  • Allows you to load the script whenever you want without worrying about script and function call order

But it also has some downsides:

  • It only works for functions where you don't need the return value. You can await the function call to get the return value, but this blocks rendering.
  • Debugging may be confusing if you're not aware of how it works.

We recommend awaiting the script load if you want to access the script's API directly.

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