v1 to v2
Nuxt Scripts 2 moves script ownership and SDK readiness onto the lifecycle APIs introduced in Unhead 3.3.1. This removes component callbacks and trigger listeners as soon as their consumer unmounts, without tearing down a script still used by other components.
Requirements
| Dependency | Required version |
|---|---|
| Node.js | >=24 |
| Nuxt | >=4.5.1, including Nuxt 5 and Nitro 3 |
@unhead/vue | >=3.3.1 <4 |
unhead | >=3.3.1 <4 |
Upgrade Nuxt and refresh its locked dependencies before installing v2:
npx nuxi@latest upgrade --force
Run the dedicated migration CLI from the project root. Preview its changes first if the project has dynamic Nuxt configuration:
npx @nuxt/scripts-cli migrate v2 --dry-run
npx @nuxt/scripts-cli migrate v2
The CLI handles static registry configuration and mechanical API renames. It lists dynamic configuration and removed components that need manual follow-up.
The module now stops setup with an actionable error when either Unhead package is missing or outside the supported range.
Registry configuration
Registry entries now accept a flat object, 'mock', or false. Nuxt Scripts 2
removes the deprecated true, 'proxy-only', tuple, nested scriptOptions,
and reverseProxyIntercept forms.
scripts: {
registry: {
- googleAnalytics: true,
- plausibleAnalytics: [{ scriptId: 'YOUR_SCRIPT_ID' }, { proxy: false }],
- calendly: { scriptOptions: { bundle: false } },
- posthog: { reverseProxyIntercept: false },
+ googleAnalytics: { trigger: 'onNuxtReady' },
+ plausibleAnalytics: { scriptId: 'YOUR_SCRIPT_ID', proxy: false },
+ calendly: { bundle: false },
+ posthog: { proxy: false },
},
}
Nuxt Scripts 2 also removes the deprecated top-level globals array. Use a
keyed object so each script has a stable name.
Google Maps
Nuxt Scripts 2 removes these v1 compatibility aliases and components:
| Removed | Replacement |
|---|---|
center and zoom props on <ScriptGoogleMaps> | mapOptions.center and mapOptions.zoom |
googleMaps template ref key | mapsApi |
overlay template ref key | overlayView |
<ScriptGoogleMapsAdvancedMarkerElement> | <ScriptGoogleMapsMarker> |
<ScriptGoogleMapsPinElement> | The marker #content slot |
<ScriptGoogleMapsHeatmapLayer> | A maintained heatmap library such as deck.gl |
Google removed HeatmapLayer from Maps JavaScript API v3.65, so Nuxt Scripts
no longer ships a component that depends on it.
Nuxt Scripts 2 removes the legacy googleStaticMapsProxy option and the
billable Google Maps server proxies. Static maps load directly from Google with
the public browser key. resolveQueryToLatLng() uses the client Places service.
Apply website and API restrictions to the key, then configure quota limits.
Registry APIs
Nuxt Scripts 2 removes these deprecated registry API shapes:
| Removed | Replacement |
|---|---|
proxy.rybbit.pageview() | proxy.pageview() |
proxy.ttq('page') | proxy.ttq.page() |
proxy.ttq('track', ...) | proxy.ttq.track(...) |
Matomo trackPageView option | watch, which defaults to true |
Plausible domain and extension options | scriptId and current init options |
Consumer scopes
Every useScript() call now returns an Unhead consumer scope.
Component unmount automatically releases callbacks and trigger listeners owned
by that call.
dispose()releases only the current consumer.signalaborts when you dispose that consumer or any caller removes the shared script.scriptpoints to the shared script instance.remove()still removes the shared script for all consumers.
If application code used remove() as component cleanup, switch it
to dispose(). In Vue components, manual cleanup is normally no
longer necessary.
Custom readiness callbacks
The use option remains supported. Callback-driven SDKs should migrate
to resolve({ waitFor }), which automatically removes listeners and
rejects pending readiness when the script lifecycle ends.
const script = useScript('https://example.com/sdk.js', {
- use: () => readyPromise.then(() => window.example),
+ resolve: ({ waitFor }) => waitFor((resolve) => {
+ window.onExampleReady = () => resolve(window.example)
+ return () => delete window.onExampleReady
+ }),
})
The bundled Google Maps, YouTube Player, Crisp, and Usercentrics integrations
now use this API. load() resolves only after each vendor's concrete
SDK API is ready.
Script triggers
Nuxt's idle-timeout, interaction, and service-worker helpers now return Unhead
trigger functions. Existing scriptOptions.trigger usage is unchanged. Custom
trigger functions may return a cleanup callback; Unhead calls it when the
consumer scope is disposed.