Skip to content

Commit 343573d

Browse files
committed
chore: bump
1 parent 9293d18 commit 343573d

88 files changed

Lines changed: 1907 additions & 1943 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,44 @@
11
---
22
title: Introduction
3-
description: Nuxt Scripts is Nuxt DX for third-party scripts.
3+
description: Load third-party scripts in Nuxt with typed APIs, loading controls, and privacy defaults.
44
---
55

6-
Nuxt Scripts enhances the performance, privacy, and developer experience (DX) when incorporating third-party scripts into Nuxt applications.
6+
Nuxt Scripts gives Nuxt apps a consistent way to load third-party scripts, with controls for timing, privacy, and type safety.
77

88
## Background
99

10-
Using the `useHead` composable to load third-party IIFE scripts is straightforward, but complexities arise with server-side rendering (SSR), lazy loading, and type safety. Nuxt Scripts addresses these challenges by optimizing third-party script integration to improve performance, privacy, and overall DX.
10+
`useHead` works well for adding a script tag. The setup becomes harder once the script must account for server-side rendering (SSR), delayed loading, or a typed global API. Nuxt Scripts handles those cases through one API.
1111

1212
### Third-Party Script Challenges
1313

14-
- Compatibility across client and server-side environments.
15-
- Application of best-practice defaults.
16-
- Granular optimization controls.
17-
- Avoiding render-blocking, privacy issues, and performance bottlenecks.
18-
- Ensuring type safety and script validation.
19-
- Security considerations with third-party servers.
14+
- Running safely in both client and server code.
15+
- Choosing when the browser loads a script.
16+
- Avoiding render-blocking work and unnecessary data exposure.
17+
- Validating configuration and typing the script API.
2018

2119
### How Third Parties Can Impact User Experience
2220

23-
Third-party resources like analytics tools, video embeds, maps, and social media integrations enhance website functionality but aren't directly managed by site owners. A single resource may have a minimal performance impact, but multiple resources can significantly degrade user experience. Scripts, in particular, can delay interactivity and obstruct page rendering.
21+
Analytics, video embeds, maps, and social widgets all run code that you do not control. One integration may be cheap; several can compete with hydration, delay interactivity, and block rendering.
2422

25-
According to the Chrome User Experience Report, Nuxt sites with numerous third-party resources typically show lower [Interaction to Next Paint (INP)](https://web.dev/articles/inp) and [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) scores. Despite the correlation not proving causation, lab tests and the [2022 Web Almanac chapter on Third Parties](https://almanac.httparchive.org/en/2022/third-parties) confirm significant performance impacts from third-party resources.
23+
[Third-party scripts can add network overhead and delay document parsing](https://web.dev/articles/third-party-javascript), depending on how they load. The [2025 Web Almanac chapter on Third Parties](https://almanac.httparchive.org/en/2025/third-parties) found that request counts rose even as pages contacted fewer unique third-party domains. Counting vendors alone can therefore understate how much work they add to a page.
2624

27-
## Nuxt Script Features
25+
## Nuxt Scripts Features
2826

29-
### 🏎️ Performance
27+
### Loading
3028

31-
- Nuxt triggers script loading only when ready, by default.
32-
- More advanced triggering of script loads, independent of implementation specifics.
33-
- Improved script loading times with [First-Party Mode](/docs/guides/first-party).
29+
- By default, scripts load with the `onNuxtReady` trigger, after hydration and during an idle period.
30+
- Trigger scripts from consent, visibility, interaction, or application state.
31+
- Serve supported scripts from your origin with [First-Party Mode](/docs/guides/first-party).
3432

35-
### 😌 Developer Experience
33+
### Developer APIs
3634

37-
- A curated script registry for common third-party applications.
38-
- Simplified analytics event management, e.g., tracking page views.
35+
- Registry entries for common third-party applications.
36+
- Page-event helpers for analytics integrations.
3937
- Input validation for script options.
4038
- Type safety and SSR-compliant APIs.
4139

42-
### 🔒 Privacy
40+
### Privacy
4341

44-
- Minimize user data exposure with the [privacy focused proxy](/docs/guides/first-party).
42+
- Minimize user data exposure with the [privacy-focused proxy](/docs/guides/first-party).
4543
- Integrated consent management.
46-
- Enhanced script privacy settings such as `crossorigin="anonymous"` and `referrerpolicy="no-referrer"`.
44+
- Privacy defaults such as `crossorigin="anonymous"` and `referrerpolicy="no-referrer"`.
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
---
22
title: Installation
3-
description: Learn how to create a Nuxt Scripts project or add it to your current Nuxt project.
3+
description: Install Nuxt Scripts in an existing Nuxt project.
44
---
55

66
## Quick Start
77

8-
To get started, simply run:
8+
Nuxt Scripts 1.x requires Nuxt 3.16 or newer.
9+
10+
Run:
911

1012
```bash
1113
npx nuxi@latest module add scripts
1214
```
1315

1416
> [!TIP]
15-
> Generate an Agent Skill for this package using [skilld](https://github.com/harlan-zw/skilld):
17+
> Generate an Agent Skill for this package using [skilld](https://github.com/skilld-dev/skilld):
1618
> ```bash
1719
> npx skilld add @nuxt/scripts
1820
> ```
1921
20-
That's it. The Nuxt Scripts module should be downloaded and added to your Nuxt Config `modules`.
22+
The [Nuxt module command](https://nuxt.com/docs/api/commands/module) installs Nuxt Scripts and adds it to the `modules` array in your Nuxt config.
2123
2224
## Next Steps
2325
24-
Need some inspiration to start using Nuxt Scripts? Try out the following:
26+
From here, choose the guide closest to what you need:
2527
26-
1. 🎉 Make it rain emojis with the [Confetti Tutorial](/docs/getting-started/confetti-tutorial).
27-
2. 📚 Learn about how the [Script Loading](/docs/guides/script-triggers) works.
28-
3. 🔍 Explore the [Script Registry](/scripts) for popular pre-configured third-party scripts.
29-
3. 🚀 Load other scripts with [`useScript()`{lang="ts"}](/docs/api/use-script){lang="ts"} or [Global Scripts](/docs/guides/global).
30-
4. 🔨 Fine-tune your performance and privacy with [First-Party Mode](/docs/guides/first-party) and [Consent Management](/docs/guides/consent).
28+
1. Build a small integration with the [Confetti Tutorial](/docs/getting-started/confetti-tutorial).
29+
2. Learn when scripts load in [Script Triggers](/docs/guides/script-triggers).
30+
3. Check the [Script Registry](/scripts) for a preconfigured integration.
31+
4. Load an unlisted script with [`useScript()`{lang="ts"}](/docs/api/use-script){lang="ts"} or [Global Scripts](/docs/guides/global).
32+
5. Configure [First-Party Mode](/docs/guides/first-party) or [Consent Management](/docs/guides/consent).

docs/content/docs/1.getting-started/3.confetti-tutorial.md

Lines changed: 55 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,17 @@ title: "Tutorial: Load js-confetti"
33
description: "Learn how to load the js-confetti script using the Nuxt Scripts module."
44
---
55

6-
## Introduction
7-
8-
In this tutorial, you will learn how to load the [js-confetti](https://github.com/loonywizard/js-confetti) script using the Nuxt Scripts module.
9-
10-
You'll learn about the following:
11-
- What the [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} registry script is.
12-
- How to load the `js-confetti` script using it.
13-
- Adding types to loaded scripts.
14-
- Using [proxied functions](/docs/guides/key-concepts#understanding-proxied-functions) to call the script.
6+
This tutorial loads [js-confetti](https://github.com/loonywizard/js-confetti) from [npm](https://npmjs.com). You'll call it through a proxied function and add types for its browser API.
157

168
## Background on [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"}
179

18-
To load the script, we'll be using the [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"}.
19-
20-
This is a [registry script](/scripts), a supported
21-
third-party integration built on top of the
22-
[`useScript()`{lang="ts"}](/docs/api/use-script){lang="ts"} composable that allows you to load scripts from [npm](https://npmjs.com).
10+
[`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} is a [registry script](/scripts) built on [`useScript()`{lang="ts"}](/docs/api/use-script){lang="ts"}. It loads browser-ready package files published to [npm](https://www.npmjs.com/).
2311

24-
When working with npm files, you'd typically include them as a `node_module` dependency in the `package.json` file. However,
25-
optimizing the script loading of these scripts can be difficult, requiring a dynamic import of the module from a separate chunk and
26-
loading it only when needed. It also slows down your build as the module needs to be transpiled.
12+
Most npm packages belong in `package.json`. Loading one on demand may instead require a dynamic import, a separate chunk, and sometimes build-time transpilation.
2713

28-
The [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} registry script abstracts this process, allowing you to load scripts that export immediately invokable functions,
29-
with a single line of code .
14+
`useScriptNpm()`{lang="ts"} is useful for an occasional, non-critical browser script that already exposes a global API. Install packages your application uses throughout the codebase as normal dependencies.
3015

31-
In many instances it will still make more sense to include the script as a dependency in the `package.json` file, but for scripts that are not used often or
32-
are not critical to the application, this can be a great alternative.
33-
34-
To begin with we can think of using this script as an alternative to the `useHead` composable. You can see an example of the abstraction
35-
layers in the following code sample.
16+
The three snippets below load the same file at different abstraction levels.
3617

3718
::code-group
3819

@@ -51,7 +32,7 @@ useScript('https://unpkg.com/js-confetti@0.12.0/dist/js-confetti.browser.js')
5132
```ts [useHead]
5233
useHead({
5334
script: [
54-
{ src: 'https://cdn.jsdelivr.net/npm/js-confetti@latest/dist/js-confetti.browser.js' }
35+
{ src: 'https://unpkg.com/js-confetti@0.12.0/dist/js-confetti.browser.js' }
5536
]
5637
})
5738
```
@@ -60,7 +41,7 @@ useHead({
6041

6142
### Loading the script
6243

63-
Within one of your components, you'll want to load the script. You can do this by using the [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} registry script.
44+
Call [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} inside a component:
6445

6546
```vue [app.vue]
6647
<script setup lang="ts">
@@ -72,14 +53,11 @@ useScriptNpm({
7253
</script>
7354
```
7455

75-
If you check your browser requests, you should see the script load.
56+
The browser's Network panel should now show the script request.
7657

7758
### Resolving the third-party script API
7859

79-
Now that the script loads, you can use it in your component. To do so we need to tell the basic API how to use the script, for this we can
80-
Use the [use](/docs/api/use-script#use) function.
81-
82-
This function runs only on the client-side to resolve the third-party script.
60+
Tell Nuxt Scripts how to resolve the script's client-side API with the [`use`](/docs/api/use-script#nuxtusescriptoptions) function:
8361

8462
```vue [app.vue]
8563
<script setup lang="ts">
@@ -99,17 +77,13 @@ useScriptNpm({
9977

10078
### Using the third-party script API
10179

102-
Now that we have a way to resolve the third-party script API, we can start using it.
80+
The `js-confetti` library exposes a `JSConfetti` class. Create an instance after the script loads, then reuse that instance for subsequent calls.
10381

104-
The `js-confetti` library requires us to instantiate a new instance of the `JSConfetti` class everytime it's used,
105-
the most compatible way to handle this is to wait for the script to load explicitly.
106-
107-
However, we can also make use of [proxied functions](/docs/guides/key-concepts#understanding-proxied-functions) if we prefer an easier to use API. Note that this will break
108-
when switching between pages as you must call `new window.JSConfetti()`{lang="ts"} between pages.
82+
You can wait for the script explicitly or use a [proxied function](/docs/guides/key-concepts#understanding-proxied-functions) to queue a call until it is ready.
10983

11084
::code-group
11185

112-
```vue [Explicit script Load]
86+
```vue [Explicit Load]
11387
<script setup lang="ts">
11488
const { onLoaded } = useScriptNpm({
11589
packageName: 'js-confetti',
@@ -140,28 +114,26 @@ const { proxy } = useScriptNpm({
140114
}
141115
})
142116
onMounted(() => {
143-
// just works
117+
// Queued until js-confetti is ready
144118
proxy.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
145119
})
146120
</script>
147121
```
148122

149123
::
150124

151-
Congrats. You should see some emojis once the script loads in.
152-
153-
However, you'll notice that we have an issue with types here. The `addConfetti` function is not typed, so we don't get any intellisense or type checking.
125+
`addConfetti` is still untyped, so the editor cannot check its arguments or offer completion.
154126

155127
### Adding types
156128

157-
You can use the generic from the [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} composable to add types to the script and add global types to the window object.
129+
Pass a generic to [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} and augment `Window` with the same API:
158130

159131
```vue [app.vue]
160132
<script setup lang="ts">
161133
export interface JSConfettiApi {
162134
JSConfetti: {
163-
new (): {
164-
addConfetti: (options?: { emojis: string[] }) => void
135+
new (config?: { canvas?: HTMLCanvasElement }): {
136+
addConfetti: (options?: { emojis?: string[] }) => Promise<void>
165137
}
166138
}
167139
}
@@ -180,34 +152,35 @@ const { onLoaded } = useScriptNpm<JSConfettiApi>({
180152
},
181153
},
182154
})
183-
onMounted(() => {
184-
onLoaded(({ JSConfetti }) => {
185-
const confetti = new JSConfetti()
186-
// fully typed!
187-
confetti.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
188-
})
155+
onLoaded(({ JSConfetti }) => {
156+
const confetti = new JSConfetti()
157+
// Checked against JSConfettiApi
158+
confetti.addConfetti({ emojis: ['🌈', '⚡️', '💥', '✨', '💫', '🌸'] })
189159
})
190160
</script>
191161
```
192162

193-
### Bonus: Trigger-based script loading
163+
### Delay script loading
194164

195-
You can delay the loading of the script by using the `trigger` option. This can be useful if you want to load the script after a certain event or time.
165+
Use `trigger` when the script should wait for application state, an event, or a timer.
196166

197167
See the [Script Triggers](/docs/guides/script-triggers) guide for all available options.
198168

199-
#### Using a Ref
169+
#### Using a ref
200170

201-
The simplest approach is to use a `ref` - the script loads when the ref becomes truthy.
171+
A `ref` loads the script when its value becomes truthy.
202172

203173
```vue [app.vue]
204174
<script setup lang="ts">
205175
const shouldLoad = ref(false)
206-
const { onLoaded } = useScriptNpm({
207-
// ..
176+
const { onLoaded } = useScriptNpm<JSConfettiApi>({
177+
packageName: 'js-confetti',
178+
file: 'dist/js-confetti.browser.js',
179+
version: '0.12.0',
208180
scriptOptions: {
209-
trigger: shouldLoad
210-
}
181+
trigger: shouldLoad,
182+
use: () => ({ JSConfetti: window.JSConfetti }),
183+
},
211184
})
212185
onLoaded(({ JSConfetti }) => {
213186
const confetti = new JSConfetti()
@@ -226,25 +199,25 @@ onLoaded(({ JSConfetti }) => {
226199
You can also use a computed ref or getter function: `trigger: computed(() => someCondition.value)`{lang="ts"} or `trigger: () => shouldLoad.value`.
227200
::
228201

229-
#### Using Element Events
202+
#### Using element events
230203

231-
You can also use the [`useScriptTriggerElement()`{lang="ts"}](/docs/api/use-script-trigger-element){lang="ts"} composable to trigger loading based on element interactions.
204+
Use [`useScriptTriggerElement()`{lang="ts"}](/docs/api/use-script-trigger-element){lang="ts"} to wait for an element interaction.
232205

233206
```vue [app.vue]
234207
<script setup lang="ts">
235-
const mouseOverEl = ref<HTMLElement>()
236-
const { onLoaded } = useScriptNpm({
237-
// ..
208+
const mouseOverEl = ref<HTMLElement | null>(null)
209+
const { onLoaded } = useScriptNpm<JSConfettiApi>({
210+
packageName: 'js-confetti',
211+
file: 'dist/js-confetti.browser.js',
212+
version: '0.12.0',
238213
scriptOptions: {
239-
trigger: useScriptTriggerElement({ trigger: 'mouseover', el: mouseOverEl })
240-
}
214+
trigger: useScriptTriggerElement({ trigger: 'mouseover', el: mouseOverEl }),
215+
use: () => ({ JSConfetti: window.JSConfetti }),
216+
},
241217
})
242-
// ..
243-
onMounted(() => {
244-
onLoaded(({ JSConfetti }) => {
245-
const confetti = new JSConfetti()
246-
confetti.addConfetti({ emojis: ['L', 'O', 'A', 'D', 'E', 'D'] })
247-
})
218+
onLoaded(({ JSConfetti }) => {
219+
const confetti = new JSConfetti()
220+
confetti.addConfetti({ emojis: ['L', 'O', 'A', 'D', 'E', 'D'] })
248221
})
249222
</script>
250223
@@ -255,28 +228,23 @@ onMounted(() => {
255228
</template>
256229
```
257230

258-
### Bonus: Bundling the script
231+
### Bundle the script locally
259232

260-
As the script is from npm and versioned, we can safely bundle it with our application. This will reduce the number of DNS requests needed, improving the performance of our application.
233+
Nuxt Scripts bundles statically analyzable `useScriptNpm()`{lang="ts"} files by default and serves them from `/_scripts/assets/`. This avoids the initial connection to the package CDN.
261234

262-
To bundle the script, you can use the `bundle` option.
235+
Set `bundle: false` if you want to load the file directly from the configured CDN instead.
263236

264237
```vue [app.vue]
265238
<script setup lang="ts">
266-
const script = useScriptNpm({
267-
// ...
239+
useScriptNpm({
240+
packageName: 'js-confetti',
241+
file: 'dist/js-confetti.browser.js',
242+
version: '0.12.0',
268243
scriptOptions: {
269-
bundle: true
270-
}
244+
bundle: false,
245+
},
271246
})
272-
// ..
273247
</script>
274248
```
275249

276-
You should see the script loaded in from your apps server.
277-
278-
## Conclusion
279-
280-
In this tutorial, you learned how to load the `js-confetti` script using the [`useScriptNpm()`{lang="ts"}](/scripts/npm){lang="ts"} registry script.
281-
282-
To learn more about the specific concepts you explored, check out the documentation for [Key concepts](/docs/guides/key-concepts).
250+
Without this opt-out, the Network panel shows the script loading from your application's server. See [Key Concepts](/docs/guides/key-concepts) for more on script instances and proxied functions.

docs/content/docs/1.getting-started/4.reproductions.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@ title: Submitting an issue
33
description: Use StackBlitz to create reproductions when troubleshooting issues with the module.
44
---
55

6-
To submit an issue against the [Nuxt Scripts](https://github.com/nuxt/scripts) module, you will need to create a reproduction.
6+
Include a minimal reproduction when you open an issue against [Nuxt Scripts](https://github.com/nuxt/scripts).
77

8-
## Creating a Reproduction
8+
## Create a reproduction
99

10-
Making reproductions for issues is a vital first step in getting help, learn more about [Why We Need Reproductions](https://antfu.me/posts/why-reproductions-are-required).
10+
A reproduction separates the module problem from the rest of your application. Nuxt's [bug-reporting guide](https://nuxt.com/docs/4.x/community/reporting-bugs#create-a-minimal-reproduction) explains how to isolate the problem and remove unrelated code.
1111

12-
The easiest way to create a reproduction is to use the [StackBlitz](https://stackblitz.com) playgrounds provided below.
12+
Start from the [StackBlitz](https://stackblitz.com) playground below. You can test the module there before trimming the project down for an issue.
1313

14-
You can use these to experiment with the module in a sandbox environment or to create a reproduction for an issue.
15-
16-
## StackBlitz Playgrounds
14+
## StackBlitz playground
1715

1816
- [Minimal Nuxt Scripts](https://stackblitz.com/edit/nuxt-starter-pkwfkx?file=pages%2Findex.vue)

0 commit comments

Comments
 (0)