@nuxt/docs 4.1.3 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/1.getting-started/02.installation.md +4 -4
  2. package/1.getting-started/03.configuration.md +4 -4
  3. package/1.getting-started/04.views.md +2 -2
  4. package/1.getting-started/05.assets.md +1 -1
  5. package/1.getting-started/06.styling.md +11 -11
  6. package/1.getting-started/07.routing.md +4 -0
  7. package/1.getting-started/09.transitions.md +6 -6
  8. package/1.getting-started/10.data-fetching.md +14 -14
  9. package/1.getting-started/11.state-management.md +2 -2
  10. package/1.getting-started/12.error-handling.md +4 -4
  11. package/1.getting-started/13.server.md +4 -4
  12. package/1.getting-started/14.layers.md +29 -10
  13. package/1.getting-started/17.testing.md +3 -3
  14. package/1.getting-started/18.upgrade.md +205 -48
  15. package/2.guide/1.directory-structure/1.app/1.components.md +4 -4
  16. package/2.guide/1.directory-structure/1.app/1.composables.md +1 -1
  17. package/2.guide/1.directory-structure/1.app/1.layouts.md +2 -2
  18. package/2.guide/1.directory-structure/1.app/1.middleware.md +4 -4
  19. package/2.guide/1.directory-structure/1.app/1.pages.md +13 -13
  20. package/2.guide/1.directory-structure/1.app/1.plugins.md +1 -5
  21. package/2.guide/1.directory-structure/1.node_modules.md +1 -1
  22. package/2.guide/1.directory-structure/1.public.md +1 -1
  23. package/2.guide/1.directory-structure/1.server.md +5 -5
  24. package/2.guide/1.directory-structure/2.env.md +1 -1
  25. package/2.guide/1.directory-structure/3.tsconfig.md +38 -7
  26. package/2.guide/2.concepts/1.auto-imports.md +2 -2
  27. package/2.guide/2.concepts/10.nuxt-lifecycle.md +3 -3
  28. package/2.guide/2.concepts/2.vuejs-development.md +3 -3
  29. package/2.guide/2.concepts/3.rendering.md +4 -4
  30. package/2.guide/2.concepts/7.esm.md +7 -3
  31. package/2.guide/2.concepts/8.typescript.md +15 -38
  32. package/2.guide/2.concepts/9.code-style.md +1 -1
  33. package/2.guide/3.going-further/1.experimental-features.md +94 -6
  34. package/2.guide/3.going-further/1.features.md +15 -3
  35. package/2.guide/3.going-further/1.internals.md +2 -2
  36. package/2.guide/3.going-further/2.hooks.md +1 -1
  37. package/2.guide/3.going-further/3.modules.md +112 -29
  38. package/2.guide/3.going-further/6.nuxt-app.md +5 -5
  39. package/2.guide/3.going-further/7.layers.md +46 -21
  40. package/2.guide/3.going-further/9.debugging.md +1 -1
  41. package/2.guide/4.recipes/1.custom-routing.md +4 -4
  42. package/2.guide/4.recipes/2.vite-plugin.md +41 -0
  43. package/2.guide/4.recipes/3.custom-usefetch.md +1 -1
  44. package/2.guide/5.best-practices/hydration.md +1 -1
  45. package/3.api/1.components/10.nuxt-picture.md +1 -1
  46. package/3.api/1.components/11.teleports.md +1 -1
  47. package/3.api/1.components/12.nuxt-route-announcer.md +1 -1
  48. package/3.api/1.components/13.nuxt-time.md +5 -1
  49. package/3.api/1.components/2.nuxt-page.md +1 -1
  50. package/3.api/1.components/4.nuxt-link.md +11 -11
  51. package/3.api/1.components/5.nuxt-loading-indicator.md +1 -1
  52. package/3.api/1.components/6.nuxt-error-boundary.md +1 -1
  53. package/3.api/2.composables/use-app-config.md +1 -1
  54. package/3.api/2.composables/use-async-data.md +80 -13
  55. package/3.api/2.composables/use-cookie.md +7 -7
  56. package/3.api/2.composables/use-fetch.md +6 -2
  57. package/3.api/2.composables/use-head-safe.md +37 -20
  58. package/3.api/2.composables/use-head.md +136 -36
  59. package/3.api/2.composables/use-hydration.md +24 -18
  60. package/3.api/2.composables/use-lazy-async-data.md +58 -9
  61. package/3.api/2.composables/use-lazy-fetch.md +65 -9
  62. package/3.api/2.composables/use-nuxt-app.md +7 -7
  63. package/3.api/2.composables/use-nuxt-data.md +1 -1
  64. package/3.api/2.composables/use-request-fetch.md +1 -1
  65. package/3.api/2.composables/use-route.md +1 -1
  66. package/3.api/2.composables/use-router.md +15 -15
  67. package/3.api/2.composables/use-runtime-hook.md +1 -1
  68. package/3.api/2.composables/use-state.md +1 -1
  69. package/3.api/3.utils/abort-navigation.md +2 -2
  70. package/3.api/3.utils/define-lazy-hydration-component.md +4 -4
  71. package/3.api/3.utils/define-nuxt-component.md +1 -1
  72. package/3.api/3.utils/define-nuxt-plugin.md +1 -1
  73. package/3.api/3.utils/define-nuxt-route-middleware.md +1 -1
  74. package/3.api/3.utils/define-page-meta.md +8 -8
  75. package/3.api/3.utils/navigate-to.md +5 -5
  76. package/3.api/3.utils/on-before-route-leave.md +1 -1
  77. package/3.api/3.utils/on-before-route-update.md +1 -1
  78. package/3.api/3.utils/refresh-cookie.md +1 -1
  79. package/3.api/3.utils/update-app-config.md +2 -2
  80. package/3.api/5.kit/1.modules.md +88 -2
  81. package/3.api/5.kit/11.nitro.md +4 -0
  82. package/3.api/5.kit/14.builder.md +66 -10
  83. package/3.api/5.kit/15.examples.md +3 -5
  84. package/3.api/5.kit/2.programmatic.md +2 -2
  85. package/3.api/5.kit/5.components.md +1 -0
  86. package/3.api/5.kit/9.head.md +132 -0
  87. package/3.api/6.advanced/1.hooks.md +7 -7
  88. package/3.api/6.nuxt-config.md +100 -29
  89. package/5.community/3.reporting-bugs.md +3 -3
  90. package/5.community/4.contribution.md +1 -1
  91. package/5.community/5.framework-contribution.md +8 -8
  92. package/5.community/6.roadmap.md +4 -4
  93. package/6.bridge/4.plugins-and-middleware.md +1 -1
  94. package/7.migration/2.configuration.md +2 -2
  95. package/7.migration/20.module-authors.md +1 -1
  96. package/7.migration/5.plugins-and-middleware.md +1 -1
  97. package/7.migration/6.pages-and-layouts.md +2 -2
  98. package/README.md +1 -1
  99. package/package.json +1 -1
@@ -18,9 +18,9 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
18
18
 
19
19
  ```vue [app/pages/index.vue]
20
20
  <script setup lang="ts">
21
- const { data, status, error, refresh, clear } = await useAsyncData(
21
+ const { data, status, pending, error, refresh, clear } = await useAsyncData(
22
22
  'mountains',
23
- () => $fetch('https://api.nuxtjs.dev/mountains'),
23
+ (_nuxtApp, { signal }) => $fetch('https://api.nuxtjs.dev/mountains', { signal }),
24
24
  )
25
25
  </script>
26
26
  ```
@@ -30,7 +30,7 @@ If you're using a custom useAsyncData wrapper, do not await it in the composable
30
30
  ::
31
31
 
32
32
  ::note
33
- `data`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
33
+ `data`, `status`, `pending` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
34
34
  ::
35
35
 
36
36
  ### Watch Params
@@ -42,10 +42,11 @@ The built-in `watch` option allows automatically rerunning the fetcher function
42
42
  const page = ref(1)
43
43
  const { data: posts } = await useAsyncData(
44
44
  'posts',
45
- () => $fetch('https://fakeApi.com/posts', {
45
+ (_nuxtApp, { signal }) => $fetch('https://fakeApi.com/posts', {
46
46
  params: {
47
47
  page: page.value,
48
48
  },
49
+ signal,
49
50
  }), {
50
51
  watch: [page],
51
52
  },
@@ -70,6 +71,64 @@ const { data: user } = useAsyncData(
70
71
  </script>
71
72
  ```
72
73
 
74
+ ### Make your `handler` abortable
75
+
76
+ You can make your `handler` function abortable by using the `signal` provided in the second argument. This is useful for cancelling requests when they are no longer needed, such as when a user navigates away from a page. `$fetch` natively supports abort signals.
77
+
78
+ ```ts
79
+ const { data, error } = await useAsyncData(
80
+ 'users',
81
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
82
+ )
83
+
84
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
85
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
86
+ refresh()
87
+
88
+ clear() // will cancel the latest pending handler
89
+ ```
90
+
91
+ You can also pass an `AbortSignal` to the `refresh`/`execute` function to cancel individual requests manually.
92
+
93
+ ```ts
94
+ const { refresh } = await useAsyncData(
95
+ 'users',
96
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
97
+ )
98
+ let abortController: AbortController | undefined
99
+
100
+ function handleUserAction () {
101
+ abortController = new AbortController()
102
+ refresh({ signal: abortController.signal })
103
+ }
104
+
105
+ function handleCancel () {
106
+ abortController?.abort() // aborts the ongoing refresh request
107
+ }
108
+ ```
109
+
110
+ If your `handler` function does not support abort signals, you can implement your own abort logic using the `signal` provided.
111
+
112
+ ```ts
113
+ const { data, error } = await useAsyncData(
114
+ 'users',
115
+ (_nuxtApp, { signal }) => {
116
+ return new Promise((resolve, reject) => {
117
+ signal?.addEventListener('abort', () => {
118
+ reject(new Error('Request aborted'))
119
+ })
120
+ return Promise.resolve(callback.call(this, yourHandler)).then(resolve, reject)
121
+ })
122
+ },
123
+ )
124
+ ```
125
+
126
+ The handler signal will be aborted when:
127
+
128
+ - A new request is made with `dedupe: 'cancel'`
129
+ - The `clear` function is called
130
+ - The `options.timeout` duration is exceeded
131
+
73
132
  ::warning
74
133
  [`useAsyncData`](/docs/4.x/api/composables/use-async-data) is a reserved function name transformed by the compiler, so you should not name your own function [`useAsyncData`](/docs/4.x/api/composables/use-async-data).
75
134
  ::
@@ -102,6 +161,7 @@ The `handler` function should be **side-effect free** to ensure predictable beha
102
161
  - `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
103
162
  - `cancel` - cancels existing requests when a new one is made
104
163
  - `defer` - does not make new requests at all if there is a pending request
164
+ - `timeout` - a number in milliseconds to wait before timing out the request (defaults to `undefined`, which means no timeout)
105
165
 
106
166
  ::note
107
167
  Under the hood, `lazy: false` uses `<Suspense>` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience.
@@ -115,7 +175,7 @@ You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `u
115
175
 
116
176
  ### Shared State and Option Consistency
117
177
 
118
- When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error` and `status` refs. This ensures consistency across components but requires option consistency.
178
+ When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error`, `status` and `pending` refs. This ensures consistency across components but requires option consistency.
119
179
 
120
180
  The following options **must be consistent** across all calls with the same key:
121
181
  - `handler` function
@@ -134,12 +194,12 @@ The following options **can differ** without triggering warnings:
134
194
 
135
195
  ```ts
136
196
  // ❌ This will trigger a development warning
137
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
138
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
197
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
198
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
139
199
 
140
200
  // ✅ This is allowed
141
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
142
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
201
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
202
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
143
203
  ```
144
204
 
145
205
  ::tip
@@ -158,6 +218,7 @@ Keyed state created using `useAsyncData` can be retrieved across your Nuxt appli
158
218
  - `pending`: the request is in progress
159
219
  - `success`: the request has completed successfully
160
220
  - `error`: the request has failed
221
+ - `pending`: a `Ref<boolean>` that is `true` while the request is in progress (that is, while `status.value === 'pending'`).
161
222
  - `clear`: a function that can be used to set `data` to `undefined` (or the value of `options.default()` if provided), set `error` to `undefined`, set `status` to `idle`, and mark any currently pending requests as cancelled.
162
223
 
163
224
  By default, Nuxt waits until a `refresh` is finished before it can be executed again.
@@ -169,14 +230,16 @@ If you have not fetched data on the server (for example, with `server: false`),
169
230
  ## Type
170
231
 
171
232
  ```ts [Signature]
233
+ export type AsyncDataHandler<ResT> = (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<ResT>
234
+
172
235
  export function useAsyncData<DataT, DataE> (
173
- handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
174
- options?: AsyncDataOptions<DataT>
236
+ handler: AsyncDataHandler<DataT>,
237
+ options?: AsyncDataOptions<DataT>,
175
238
  ): AsyncData<DataT, DataE>
176
239
  export function useAsyncData<DataT, DataE> (
177
240
  key: MaybeRefOrGetter<string>,
178
- handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
179
- options?: AsyncDataOptions<DataT>
241
+ handler: AsyncDataHandler<DataT>,
242
+ options?: AsyncDataOptions<DataT>,
180
243
  ): Promise<AsyncData<DataT, DataE>>
181
244
 
182
245
  type AsyncDataOptions<DataT> = {
@@ -190,6 +253,7 @@ type AsyncDataOptions<DataT> = {
190
253
  pick?: string[]
191
254
  watch?: MultiWatchSources | false
192
255
  getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
256
+ timeout?: number
193
257
  }
194
258
 
195
259
  type AsyncDataRequestContext = {
@@ -204,10 +268,13 @@ type AsyncData<DataT, ErrorT> = {
204
268
  clear: () => void
205
269
  error: Ref<ErrorT | undefined>
206
270
  status: Ref<AsyncDataRequestStatus>
271
+ pending: Ref<boolean>
207
272
  }
208
273
 
209
274
  interface AsyncDataExecuteOptions {
210
275
  dedupe?: 'cancel' | 'defer'
276
+ timeout?: number
277
+ signal?: AbortSignal
211
278
  }
212
279
 
213
280
  type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
@@ -42,7 +42,7 @@ export interface CookieRef<T> extends Ref<T> {}
42
42
 
43
43
  export function useCookie<T = string | null | undefined> (
44
44
  name: string,
45
- options?: CookieOptions<T>
45
+ options?: CookieOptions<T>,
46
46
  ): CookieRef<T>
47
47
  ```
48
48
 
@@ -61,14 +61,14 @@ Most of the options will be directly passed to the [cookie](https://github.com/j
61
61
  | `default` | `() => T \| Ref<T>` | `undefined` | Function returning the default value if the cookie does not exist. The function can also return a `Ref`. |
62
62
  | `watch` | `boolean \| 'shallow'` | `true` | Whether to watch for changes and update the cookie. `true` for deep watch, `'shallow'` for shallow watch, i.e. data changes for only top level properties, `false` to disable. <br/> **Note:** Refresh `useCookie` values manually when a cookie has changed with [`refreshCookie`](/docs/4.x/api/utils/refresh-cookie). |
63
63
  | `readonly` | `boolean` | `false` | If `true`, disables writing to the cookie. |
64
- | `maxAge` | `number` | `undefined` | Max age in seconds for the cookie, i.e. the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2). The given number will be converted to an integer by rounding down. By default, no maximum age is set. |
65
- | `expires` | `Date` | `undefined` | Expiration date for the cookie. By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. <br/> **Note:** The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this, so if both are set, they should point to the same date and time! <br/>If neither of `expires` and `maxAge` is set, the cookie will be session-only and removed when the user closes their browser. |
64
+ | `maxAge` | `number` | `undefined` | Max age in seconds for the cookie, i.e. the value for the [`Max-Age` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2). The given number will be converted to an integer by rounding down. By default, no maximum age is set. |
65
+ | `expires` | `Date` | `undefined` | Expiration date for the cookie. By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. <br/> **Note:** The [cookie storage model specification](https://datatracker.ietf.org/doc/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this, so if both are set, they should point to the same date and time! <br/>If neither of `expires` and `maxAge` is set, the cookie will be session-only and removed when the user closes their browser. |
66
66
  | `httpOnly` | `boolean` | `false` | Sets the HttpOnly attribute. <br/> **Note:** Be careful when setting this to `true`, as compliant clients will not allow client-side JavaScript to see the cookie in `document.cookie`. |
67
- | `secure` | `boolean` | `false` | Sets the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5). <br/>**Note:** Be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors. |
67
+ | `secure` | `boolean` | `false` | Sets the [`Secure` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5). <br/>**Note:** Be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors. |
68
68
  | `partitioned` | `boolean` | `false` | Sets the [`Partitioned` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/draft-cutler-httpbis-partitioned-cookies#section-2.1). <br/>**Note:** This is an attribute that has not yet been fully standardized, and may change in the future. <br/>This also means many clients may ignore this attribute until they understand it.<br/>More information can be found in the [proposal](https://github.com/privacycg/CHIPS). |
69
- | `domain` | `string` | `undefined` | Sets the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3). By default, no domain is set, and most clients will consider applying the cookie only to the current domain. |
70
- | `path` | `string` | `'/'` | Sets the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4). By default, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4). |
71
- | `sameSite` | `boolean \| string` | `undefined` | Sets the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7). <br/>- `true` will set the `SameSite` attribute to `Strict` for strict same-site enforcement.<br/>- `false` will not set the `SameSite` attribute.<br/>- `'lax'` will set the `SameSite` attribute to `Lax` for lax same-site enforcement.<br/>- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.<br/>- `'strict'` will set the `SameSite` attribute to `Strict` for strict same-site enforcement. |
69
+ | `domain` | `string` | `undefined` | Sets the [`Domain` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3). By default, no domain is set, and most clients will consider applying the cookie only to the current domain. |
70
+ | `path` | `string` | `'/'` | Sets the [`Path` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.4). By default, the path is considered the ["default path"](https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4). |
71
+ | `sameSite` | `boolean \| string` | `undefined` | Sets the [`SameSite` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7). <br/>- `true` will set the `SameSite` attribute to `Strict` for strict same-site enforcement.<br/>- `false` will not set the `SameSite` attribute.<br/>- `'lax'` will set the `SameSite` attribute to `Lax` for lax same-site enforcement.<br/>- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.<br/>- `'strict'` will set the `SameSite` attribute to `Strict` for strict same-site enforcement. |
72
72
 
73
73
  ## Return Values
74
74
 
@@ -100,7 +100,7 @@ If you encounter the `data` variable destructured from a `useFetch` returns a st
100
100
 
101
101
  ### Reactive Fetch Options
102
102
 
103
- Fetch options can be provided as reactive, supporting `computed`, `ref` and [computed getters](https://vuejs.org/guide/essentials/computed.html). When a reactive fetch option is updated it will trigger a refetch using the updated resolved reactive value.
103
+ Fetch options can be provided as reactive, supporting `computed`, `ref` and [computed getters](https://vuejs.org/guide/essentials/computed). When a reactive fetch option is updated it will trigger a refetch using the updated resolved reactive value.
104
104
 
105
105
  ```ts
106
106
  const searchQuery = ref('initial')
@@ -128,7 +128,7 @@ searchQuery.value = 'new search'
128
128
  ```ts [Signature]
129
129
  export function useFetch<DataT, ErrorT> (
130
130
  url: string | Request | Ref<string | Request> | (() => string | Request),
131
- options?: UseFetchOptions<DataT>
131
+ options?: UseFetchOptions<DataT>,
132
132
  ): Promise<AsyncData<DataT, ErrorT>>
133
133
 
134
134
  type UseFetchOptions<DataT> = {
@@ -145,6 +145,7 @@ type UseFetchOptions<DataT> = {
145
145
  getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
146
146
  deep?: boolean
147
147
  dedupe?: 'cancel' | 'defer'
148
+ timeout?: number
148
149
  default?: () => DataT
149
150
  transform?: (input: DataT) => DataT | Promise<DataT>
150
151
  pick?: string[]
@@ -169,6 +170,8 @@ type AsyncData<DataT, ErrorT> = {
169
170
 
170
171
  interface AsyncDataExecuteOptions {
171
172
  dedupe?: 'cancel' | 'defer'
173
+ timeout?: number
174
+ signal?: AbortSignal
172
175
  }
173
176
 
174
177
  type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
@@ -195,6 +198,7 @@ type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
195
198
  | `lazy` | `boolean` | `false` | If true, resolves after route loads (does not block navigation). |
196
199
  | `immediate` | `boolean` | `true` | If false, prevents request from firing immediately. |
197
200
  | `default` | `() => DataT` | - | Factory for default value of `data` before async resolves. |
201
+ | `timeout` | `number` | - | A number in milliseconds to wait before timing out the request (defaults to `undefined`, which means no timeout) |
198
202
  | `transform` | `(input: DataT) => DataT \| Promise<DataT>` | - | Function to transform the result after resolving. |
199
203
  | `getCachedData`| `(key, nuxtApp, ctx) => DataT \| undefined` | - | Function to return cached data. See below for default. |
200
204
  | `pick` | `string[]` | - | Only pick specified keys from the result. |
@@ -8,28 +8,12 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/4.x/api/composables/use-head) composable that restricts the input to only allow safe values.
12
-
13
11
  ## Usage
14
12
 
15
- You can pass all the same values as [`useHead`](/docs/4.x/api/composables/use-head)
16
-
17
- ```ts
18
- useHeadSafe({
19
- script: [
20
- { id: 'xss-script', innerHTML: 'alert("xss")' },
21
- ],
22
- meta: [
23
- { 'http-equiv': 'refresh', 'content': '0;javascript:alert(1)' },
24
- ],
25
- })
26
- // Will safely generate
27
- // <script id="xss-script"></script>
28
- // <meta content="0;javascript:alert(1)">
29
- ```
13
+ The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/4.x/api/composables/use-head) composable that restricts the input to only allow safe values. This is the recommended way to manage head data when working with user input, as it prevents XSS attacks by sanitizing potentially dangerous attributes.
30
14
 
31
- ::read-more{to="https://unhead.unjs.io/docs/typescript/head/api/composables/use-head-safe" target="_blank"}
32
- Read more on the `Unhead` documentation.
15
+ ::warning
16
+ When using `useHeadSafe`, potentially dangerous attributes like `innerHTML` in scripts or `http-equiv` in meta tags are automatically stripped out to prevent XSS attacks. Use this composable whenever you're working with user-generated content.
33
17
  ::
34
18
 
35
19
  ## Type
@@ -38,7 +22,9 @@ Read more on the `Unhead` documentation.
38
22
  export function useHeadSafe (input: MaybeComputedRef<HeadSafe>): void
39
23
  ```
40
24
 
41
- The list of allowed values is:
25
+ ### Allowed Attributes
26
+
27
+ The following attributes are whitelisted for each head element type:
42
28
 
43
29
  ```ts
44
30
  const WhitelistAttributes = {
@@ -53,3 +39,34 @@ const WhitelistAttributes = {
53
39
  ```
54
40
 
55
41
  See [@unhead/vue](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/safeSchema.ts) for more detailed types.
42
+
43
+ ## Parameters
44
+
45
+ `input`: A `MaybeComputedRef<HeadSafe>` object containing head data. You can pass all the same values as [`useHead`](/docs/4.x/api/composables/use-head), but only safe attributes will be rendered.
46
+
47
+ ## Return Values
48
+
49
+ This composable does not return any value.
50
+
51
+ ## Example
52
+
53
+ ```vue [app/pages/user-profile.vue]
54
+ <script setup lang="ts">
55
+ // User-generated content that might contain malicious code
56
+ const userBio = ref('<script>alert("xss")<' + '/script>')
57
+
58
+ useHeadSafe({
59
+ title: `User Profile`,
60
+ meta: [
61
+ {
62
+ name: 'description',
63
+ content: userBio.value, // Safely sanitized
64
+ },
65
+ ],
66
+ })
67
+ </script>
68
+ ```
69
+
70
+ ::read-more{to="https://unhead.unjs.io/docs/typescript/head/api/composables/use-head-safe" target="_blank"}
71
+ Read more on the `Unhead` documentation.
72
+ ::
@@ -8,19 +8,38 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- The [`useHead`](/docs/4.x/api/composables/use-head) composable function allows you to manage your head tags in a programmatic and reactive way, powered by [Unhead](https://unhead.unjs.io). If the data comes from a user or other untrusted source, we recommend you check out [`useHeadSafe`](/docs/4.x/api/composables/use-head-safe).
11
+ ## Usage
12
12
 
13
- :read-more{to="/docs/4.x/getting-started/seo-meta"}
13
+ The `useHead` composable allows you to manage your head tags in a programmatic and reactive way, powered by [Unhead](https://unhead.unjs.io). It lets you customize the meta tags, links, scripts, and other elements in the `<head>` section of your HTML document.
14
+
15
+ ```vue [app/app.vue]
16
+ <script setup lang="ts">
17
+ useHead({
18
+ title: 'My App',
19
+ meta: [
20
+ { name: 'description', content: 'My amazing site.' },
21
+ ],
22
+ bodyAttrs: {
23
+ class: 'test',
24
+ },
25
+ script: [{ innerHTML: 'console.log(\'Hello world\')' }],
26
+ })
27
+ </script>
28
+ ```
29
+
30
+ ::warning
31
+ If the data comes from a user or other untrusted source, we recommend you check out [`useHeadSafe`](/docs/4.x/api/composables/use-head-safe).
32
+ ::
33
+
34
+ ::note
35
+ The properties of `useHead` can be dynamic, accepting `ref`, `computed` and `reactive` properties. The `meta` parameter can also accept a function returning an object to make the entire object reactive.
36
+ ::
14
37
 
15
38
  ## Type
16
39
 
17
40
  ```ts [Signature]
18
41
  export function useHead (meta: MaybeComputedRef<MetaObject>): void
19
- ```
20
42
 
21
- Below are the non-reactive types for [`useHead`](/docs/4.x/api/composables/use-head) .
22
-
23
- ```ts
24
43
  interface MetaObject {
25
44
  title?: string
26
45
  titleTemplate?: string | ((title?: string) => string)
@@ -35,35 +54,116 @@ interface MetaObject {
35
54
  }
36
55
  ```
37
56
 
38
- See [@unhead/vue](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/schema.ts) for more detailed types.
57
+ See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/schema.ts) for more detailed types.
39
58
 
40
- ::note
41
- The properties of `useHead` can be dynamic, accepting `ref`, `computed` and `reactive` properties. `meta` parameter can also accept a function returning an object to make the entire object reactive.
42
- ::
59
+ ## Parameters
60
+
61
+ `meta`: An object accepting head metadata properties to customize the page's `<head>` section. All properties support reactive values (`ref`, `computed`, `reactive`) or can be a function returning the metadata object.
62
+
63
+ | Property | Type | Description |
64
+ | --- | --- | --- |
65
+ | `title` | `string` | Sets the page title. |
66
+ | `titleTemplate` | `string \| ((title?: string) => string)` | Configures a dynamic template to customize the page title. Can be a string with `%s` placeholder or a function. |
67
+ | `base` | `Base` | Sets the `<base>` tag for the document. |
68
+ | `link` | `Link[]` | Array of link objects. Each element is mapped to a `<link>` tag, where object properties correspond to HTML attributes. |
69
+ | `meta` | `Meta[]` | Array of meta objects. Each element is mapped to a `<meta>` tag, where object properties correspond to HTML attributes. |
70
+ | `style` | `Style[]` | Array of style objects. Each element is mapped to a `<style>` tag, where object properties correspond to HTML attributes. |
71
+ | `script` | `Script[]` | Array of script objects. Each element is mapped to a `<script>` tag, where object properties correspond to HTML attributes. |
72
+ | `noscript` | `Noscript[]` | Array of noscript objects. Each element is mapped to a `<noscript>` tag, where object properties correspond to HTML attributes. |
73
+ | `htmlAttrs` | `HtmlAttributes` | Sets attributes of the `<html>` tag. Each object property is mapped to the corresponding attribute. |
74
+ | `bodyAttrs` | `BodyAttributes` | Sets attributes of the `<body>` tag. Each object property is mapped to the corresponding attribute. |
75
+
76
+ ## Return Values
77
+
78
+ This composable does not return any value. It registers the head metadata with Unhead, which manages the actual DOM updates.
79
+
80
+ ## Examples
81
+
82
+ ### Basic Meta Tags
43
83
 
44
- ## Params
45
-
46
- ### `meta`
47
-
48
- **Type**: `MetaObject`
49
-
50
- An object accepting the following head metadata:
51
-
52
- - `meta`: Each element in the array is mapped to a newly-created `<meta>` tag, where object properties are mapped to the corresponding attributes.
53
- - **Type**: `Array<Record<string, any>>`
54
- - `link`: Each element in the array is mapped to a newly-created `<link>` tag, where object properties are mapped to the corresponding attributes.
55
- - **Type**: `Array<Record<string, any>>`
56
- - `style`: Each element in the array is mapped to a newly-created `<style>` tag, where object properties are mapped to the corresponding attributes.
57
- - **Type**: `Array<Record<string, any>>`
58
- - `script`: Each element in the array is mapped to a newly-created `<script>` tag, where object properties are mapped to the corresponding attributes.
59
- - **Type**: `Array<Record<string, any>>`
60
- - `noscript`: Each element in the array is mapped to a newly-created `<noscript>` tag, where object properties are mapped to the corresponding attributes.
61
- - **Type**: `Array<Record<string, any>>`
62
- - `titleTemplate`: Configures dynamic template to customize the page title on an individual page.
63
- - **Type**: `string` | `((title: string) => string)`
64
- - `title`: Sets static page title on an individual page.
65
- - **Type**: `string`
66
- - `bodyAttrs`: Sets attributes of the `<body>` tag. Each object property is mapped to the corresponding attribute.
67
- - **Type**: `Record<string, any>`
68
- - `htmlAttrs`: Sets attributes of the `<html>` tag. Each object property is mapped to the corresponding attribute.
69
- - **Type**: `Record<string, any>`
84
+ ```vue [app/pages/about.vue]
85
+ <script setup lang="ts">
86
+ useHead({
87
+ title: 'About Us',
88
+ meta: [
89
+ { name: 'description', content: 'Learn more about our company' },
90
+ { property: 'og:title', content: 'About Us' },
91
+ { property: 'og:description', content: 'Learn more about our company' },
92
+ ],
93
+ })
94
+ </script>
95
+ ```
96
+
97
+ ### Reactive Meta Tags
98
+
99
+ ```vue [app/pages/profile.vue]
100
+ <script setup lang="ts">
101
+ const profile = ref({ name: 'John Doe' })
102
+
103
+ useHead({
104
+ title: computed(() => profile.value.name),
105
+ meta: [
106
+ {
107
+ name: 'description',
108
+ content: computed(() => `Profile page for ${profile.value.name}`),
109
+ },
110
+ ],
111
+ })
112
+ </script>
113
+ ```
114
+
115
+ ### Using a Function for Full Reactivity
116
+
117
+ ```vue [app/pages/dynamic.vue]
118
+ <script setup lang="ts">
119
+ const count = ref(0)
120
+
121
+ useHead(() => ({
122
+ title: `Count: ${count.value}`,
123
+ meta: [
124
+ { name: 'description', content: `Current count is ${count.value}` },
125
+ ],
126
+ }))
127
+ </script>
128
+ ```
129
+
130
+ ### Adding External Scripts and Styles
131
+
132
+ ```vue [app/pages/external.vue]
133
+ <script setup lang="ts">
134
+ useHead({
135
+ link: [
136
+ {
137
+ rel: 'stylesheet',
138
+ href: 'https://cdn.example.com/styles.css',
139
+ },
140
+ ],
141
+ script: [
142
+ {
143
+ src: 'https://cdn.example.com/script.js',
144
+ async: true,
145
+ },
146
+ ],
147
+ })
148
+ </script>
149
+ ```
150
+
151
+ ### Body and HTML Attributes
152
+
153
+ ```vue [app/pages/themed.vue]
154
+ <script setup lang="ts">
155
+ const isDark = ref(true)
156
+
157
+ useHead({
158
+ htmlAttrs: {
159
+ lang: 'en',
160
+ class: computed(() => isDark.value ? 'dark' : 'light'),
161
+ },
162
+ bodyAttrs: {
163
+ class: 'themed-page',
164
+ },
165
+ })
166
+ </script>
167
+ ```
168
+
169
+ :read-more{to="/docs/4.x/getting-started/seo-meta"}
@@ -8,6 +8,8 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
+ `useHydration` is a built-in composable that provides a way to set data on the server side every time a new HTTP request is made and receive that data on the client side. This way `useHydration` allows you to take full control of the hydration cycle.
12
+
11
13
  ::note
12
14
  This is an advanced composable, primarily designed for use within plugins, mostly used by Nuxt modules.
13
15
  ::
@@ -16,14 +18,24 @@ This is an advanced composable, primarily designed for use within plugins, mostl
16
18
  `useHydration` is designed to **ensure state synchronization and restoration during SSR**. If you need to create a globally reactive state that is SSR-friendly in Nuxt, [`useState`](/docs/4.x/api/composables/use-state) is the recommended choice.
17
19
  ::
18
20
 
19
- `useHydration` is a built-in composable that provides a way to set data on the server side every time a new HTTP request is made and receive that data on the client side. This way `useHydration` allows you to take full control of the hydration cycle.
21
+ ## Usage
20
22
 
21
23
  The data returned from the `get` function on the server is stored in `nuxtApp.payload` under the unique key provided as the first parameter to `useHydration`. During hydration, this data is then retrieved on the client, preventing redundant computations or API calls.
22
24
 
23
- ## Usage
24
-
25
25
  ::code-group
26
26
 
27
+ ```ts [With useHydration]
28
+ export default defineNuxtPlugin((nuxtApp) => {
29
+ const myStore = new MyStore()
30
+
31
+ useHydration(
32
+ 'myStoreState',
33
+ () => myStore.getState(),
34
+ data => myStore.setState(data),
35
+ )
36
+ })
37
+ ```
38
+
27
39
  ```ts [Without useHydration]
28
40
  export default defineNuxtPlugin((nuxtApp) => {
29
41
  const myStore = new MyStore()
@@ -41,18 +53,6 @@ export default defineNuxtPlugin((nuxtApp) => {
41
53
  }
42
54
  })
43
55
  ```
44
-
45
- ```ts [With useHydration]
46
- export default defineNuxtPlugin((nuxtApp) => {
47
- const myStore = new MyStore()
48
-
49
- useHydration(
50
- 'myStoreState',
51
- () => myStore.getState(),
52
- data => myStore.setState(data),
53
- )
54
- })
55
- ```
56
56
  ::
57
57
 
58
58
  ## Type
@@ -63,6 +63,12 @@ export function useHydration<T> (key: string, get: () => T, set: (value: T) => v
63
63
 
64
64
  ## Parameters
65
65
 
66
- - `key`: A unique key that identifies the data in your Nuxt application.
67
- - `get`: A function executed **only on the server** (called when SSR rendering is done) to set the initial value.
68
- - `set`: A function executed **only on the client** (called when initial vue instance is created) to receive the data.
66
+ | Parameter | Type | Description |
67
+ | --- | --- | --- |
68
+ | `key` | `string` | A unique key that identifies the data in your Nuxt application. |
69
+ | `get` | `() => T` | A function executed **only on the server** (called when SSR rendering is done) to set the initial value. |
70
+ | `set` | `(value: T) => void` | A function executed **only on the client** (called when initial Vue instance is created) to receive the data. |
71
+
72
+ ## Return Values
73
+
74
+ This composable does not return any value.