Nuxt Scripts
Better Privacy, Performance, and DX for Third-Party Scripts in Nuxt Apps.
Features
- 🪨 useScript
- 🦥 Improve your site performance with better script loading strategies
- 🎃 Powerful proxy API for SSR handling, lazy loading, and error handling
- (TODO) Registry for third-party scripts in Nuxt
- ⏬ Serve scripts from your own server
- 🕵️ Privacy Features - Trigger scripts loading on consent.
- 🪵 DevTools integration - View your script with their status and see function logs
Background
Loading third-party IIFE scripts using useHead
composable is easy. However,
things start getting more complicated quickly around SSR, lazy loading, and type safety.
Nuxt Scripts was created to solve these issues and more with the goal of making third-party scripts more performant,
have better privacy and be better DX overall.
Quick Start
To get started, simply run:
npx nuxi@latest module add @nuxt/scripts
To start using Nuxt Scripts, you can use the useScript composable to load your third-party scripts.
Confetti Example
If you want to get a feel for how the module works, you can load the js-confetti
library:
interface JSConfettiApi { addConfetti: (options?: { emojis: string[] }) => void }
const { addConfetti } = useScript<JSConfettiApi>('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {
trigger: 'onNuxtReady',
assetStrategy: 'bundle',
use() {
return new window.JSConfetti()
},
})
addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
Guides
Using The Registry (TODO)
The registry is a collection of composables and Nuxt Modules that directly integrate with Nuxt Scripts.
To use a script from the registry, simply use the composable. Consult the
below table for the available scripts.
Key | Description | Composable | Source |
---|
cloudflare-web-analytics | Cloudflare Web Analytics | useScriptCloudflareWebAnalytics | Core |
confetti | JS Confetti | useScriptCloudflareAnalytics | Core |
facebook-pixel | Facebook Pixel | useScriptFacebookPixel | Core |
fathom-analytics | Fathom Analytics | useScriptFathomAnalytics | Core |
hotjar | Hotjar | useScriptHotjar | Core |
intercom | Intercom | useScriptIntercom | Core |
segment | Segment | useScriptSegment | Core |
google-analytics | Google Analytics | useScriptGoogleAnalytics | Nuxt Third Party Capital |
google-tag-manager | Google Tag Manager | useScriptGoogleTagManager | Nuxt Third Party Capital |
google-maps | Google Maps | useScriptGoogleMaps | Nuxt Third Party Capital |
cloudflare-turnstile | CloudFlare Turnstile | useCloudflareTurnstile | Nuxt Cloudflare Turnstile |
More coming soon!
Loading Scripts Globally
If you prefer a config based approach, you can load scripts globally by defining them in your nuxt.config.ts
.
export default defineNuxtConfig({
scripts: {
globals: [
'https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js',
{
assetStrategy: 'bundle'
}
]
}
})
Bundling Scripts
Bundling scripts can allow you to serve them from your own server, improving privacy and performance. It
can also help to get around ad blockers and other privacy tools when you need a script to load.
You can opt-in to have your scripts bundled by using the assetStrategy
option. As this is
analyzed at build time, you must define it statically.
useScript('https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js', {
assetStrategy: 'bundle'
})
Overriding Scripts
When working with modules that use Nuxt Script, you may want to modify the
behavior of the script. This is especially useful for
changing the asset strategy of a script as it needs to be defined statically.
To do so you can use the overrides
module option.
export default defineNuxtConfig({
scripts: {
overrides: {
confetti: {
assetStrategy: 'bundle'
}
}
}
})
Privacy and Cookie Consent
Nuxt Scripts provides a createScriptConsentTrigger
composable that allows you to load scripts based on user's consent.
You can either use it by providing a resolvable consent (ref, promise) option or by using accept()
.
export const agreedToCookiesScriptConsent = createScriptConsentTrigger()
useScript('https://www.google-analytics.com/analytics.js', {
trigger: agreedToCookiesScriptConsent
})
agreedToCookiesScriptConsent.accept()
const agreedToCookies = ref(false)
useScript('https://www.google-analytics.com/analytics.js', {
trigger: createScriptConsentTrigger({
consent: agreedToCookies
})
})
Sending Page Events
When using tracking scripts, it's common to send an event when the page changes. Due to Nuxt's head implementation being
async, the page title is not always available on route change immediately.
useAnalyticsPageEvent
solves this by providing you with the page title and path when they change.
useAnalyticsPageEvent(({ title, path }) => {
gtag('event', 'page_view', {
page_title: title,
page_location: 'https://example.com',
page_path: path
})
})
API
useScript
Please see the useScript documentation.
createScriptConsentTrigger
(options: ScriptConsentTriggerOptions) => { accept: () => void } & Promise
Creates a consent trigger for a script.
Arguments
consent
(optional) - A ref, promise, or boolean that resolves to the user's consent. Defaults to undefined
.loadOnNuxtReady
(optional) - If consent is provided before the browser idle, wait for the browser to be idle before loading the script. Defaults to false
.
Returns
accept
- A function that can be called to accept the consent and load the script.
const trigger = createScriptConsentTrigger()
trigger.accept()
useAnalyticsPageEvent
(callback?: (page: { title: string, path: string }) => void) => Ref<{ title: string, path: string }>
Access the current page title and path and trigger an event when they change.
Arguments
callback
(optional) - A function that will be called when the page title or path changes.
Returns
- A ref containing the current page title and path.
const pageCtx = useAnalyticsPageEvent()
pageCtx.value.title
License
Licensed under the MIT license.
📑 License
Published under the MIT License