@nuxt/docs 3.20.0 → 3.20.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 (31) hide show
  1. package/1.getting-started/02.installation.md +2 -2
  2. package/1.getting-started/07.routing.md +4 -0
  3. package/1.getting-started/10.data-fetching.md +12 -12
  4. package/1.getting-started/14.layers.md +28 -9
  5. package/2.guide/1.directory-structure/1.node_modules.md +1 -1
  6. package/2.guide/1.directory-structure/3.tsconfig.md +23 -0
  7. package/2.guide/2.concepts/9.code-style.md +1 -1
  8. package/2.guide/3.going-further/1.experimental-features.md +4 -4
  9. package/2.guide/3.going-further/3.modules.md +1 -1
  10. package/2.guide/3.going-further/7.layers.md +30 -13
  11. package/2.guide/4.recipes/2.vite-plugin.md +2 -2
  12. package/3.api/2.composables/use-async-data.md +76 -13
  13. package/3.api/2.composables/use-cookie.md +1 -1
  14. package/3.api/2.composables/use-fetch.md +1 -1
  15. package/3.api/2.composables/use-head-safe.md +37 -20
  16. package/3.api/2.composables/use-head.md +136 -36
  17. package/3.api/2.composables/use-hydration.md +24 -18
  18. package/3.api/2.composables/use-lazy-async-data.md +59 -10
  19. package/3.api/2.composables/use-lazy-fetch.md +66 -10
  20. package/3.api/2.composables/use-nuxt-app.md +1 -1
  21. package/3.api/2.composables/use-nuxt-data.md +1 -1
  22. package/3.api/2.composables/use-request-fetch.md +1 -1
  23. package/3.api/2.composables/use-route.md +1 -1
  24. package/3.api/2.composables/use-runtime-hook.md +1 -1
  25. package/3.api/3.utils/navigate-to.md +1 -1
  26. package/3.api/3.utils/refresh-cookie.md +2 -2
  27. package/3.api/5.kit/1.modules.md +1 -1
  28. package/3.api/5.kit/2.programmatic.md +2 -2
  29. package/3.api/5.kit/5.components.md +1 -1
  30. package/5.community/3.reporting-bugs.md +1 -1
  31. package/package.json +1 -1
@@ -30,8 +30,8 @@ Or follow the steps below to set up a new Nuxt project on your computer.
30
30
  :summary[Additional notes for an optimal setup:]
31
31
  - **Node.js**: Make sure to use an even numbered version (20, 22, etc.)
32
32
  - **Nuxtr**: Install the community-developed [Nuxtr extension](https://marketplace.visualstudio.com/items?itemName=Nuxtr.nuxtr-vscode)
33
- - **WSL**: If you are using Windows and experience slow HMR, you may want to try using [WSL (Windows Subsystem for Linux)](https://docs.microsoft.com/en-us/windows/wsl/install) which may solve some performance issues.
34
- - **Windows slow DNS resolution** - instead of using `localhost:3000` for local dev server on Windows, use `127.0.0.1` for much faster loading experience on browsers.
33
+ - **WSL**: If you are using Windows and experience slow HMR, you may want to try using [WSL (Windows Subsystem for Linux)](https://learn.microsoft.com/en-us/windows/wsl/install) which may solve some performance issues.
34
+ - **Windows slow DNS resolution**: Instead of using `localhost:3000` for local dev server on Windows, use `127.0.0.1` for much faster loading experience on browsers.
35
35
  ::
36
36
  ::
37
37
 
@@ -90,6 +90,10 @@ Nuxt provides a customizable route middleware framework you can use throughout y
90
90
  Route middleware runs within the Vue part of your Nuxt app. Despite the similar name, they are completely different from server middleware, which are run in the Nitro server part of your app.
91
91
  ::
92
92
 
93
+ ::important
94
+ Route middleware does **not** run for server routes (e.g. `/api/*`) or other server requests. To apply middleware to these requests, use [server middleware](/docs/3.x/guide/directory-structure/server#server-middleware) instead.
95
+ ::
96
+
93
97
  There are three kinds of route middleware:
94
98
 
95
99
  1. Anonymous (or inline) route middleware, which are defined directly in the pages where they are used.
@@ -194,10 +194,10 @@ The `useAsyncData` composable is a great way to wrap and wait for multiple `$fet
194
194
 
195
195
  ```vue
196
196
  <script setup lang="ts">
197
- const { data: discounts, status } = await useAsyncData('cart-discount', async () => {
197
+ const { data: discounts, status } = await useAsyncData('cart-discount', async (_nuxtApp, { signal }) => {
198
198
  const [coupons, offers] = await Promise.all([
199
- $fetch('/cart/coupons'),
200
- $fetch('/cart/offers'),
199
+ $fetch('/cart/coupons', { signal }),
200
+ $fetch('/cart/offers', { signal }),
201
201
  ])
202
202
 
203
203
  return { coupons, offers }
@@ -372,8 +372,8 @@ The following options **must be consistent** across all calls with the same key:
372
372
 
373
373
  ```ts
374
374
  // ❌ This will trigger a development warning
375
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
376
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
375
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
376
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
377
377
  ```
378
378
 
379
379
  The following options **can safely differ** without triggering warnings:
@@ -385,16 +385,16 @@ The following options **can safely differ** without triggering warnings:
385
385
 
386
386
  ```ts
387
387
  // ✅ This is allowed
388
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
389
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
388
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
389
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
390
390
  ```
391
391
 
392
392
  If you need independent instances, use different keys:
393
393
 
394
394
  ```ts
395
395
  // These are completely independent instances
396
- const { data: users1 } = useAsyncData('users-1', () => $fetch('/api/users'))
397
- const { data: users2 } = useAsyncData('users-2', () => $fetch('/api/users'))
396
+ const { data: users1 } = useAsyncData('users-1', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }))
397
+ const { data: users2 } = useAsyncData('users-2', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }))
398
398
  ```
399
399
 
400
400
  #### Reactive Keys
@@ -804,10 +804,10 @@ while (true) {
804
804
  When requests don't rely on each other, you can make them in parallel with `Promise.all()` to boost performance.
805
805
 
806
806
  ```ts
807
- const { data } = await useAsyncData(() => {
807
+ const { data } = await useAsyncData((_nuxtApp, { signal }) => {
808
808
  return Promise.all([
809
- $fetch('/api/comments/'),
810
- $fetch('/api/author/12'),
809
+ $fetch('/api/comments/', { signal }),
810
+ $fetch('/api/author/12', { signal }),
811
811
  ])
812
812
  })
813
813
 
@@ -80,27 +80,46 @@ Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io
80
80
 
81
81
  ## Layer Priority
82
82
 
83
- When using multiple layers, it's important to understand how they override each other:
83
+ When using multiple layers, it's important to understand the override order. Layers with **higher priority** override layers with lower priority when they define the same files or components.
84
84
 
85
- 1. **Layers in `extends`** - earlier entries have higher priority (first overrides second)
86
- 2. **Auto-scanned local layers** from `~~/layers` directory in alphabetical order (Z overrides A)
87
- 3. **Your project** has the highest priority in the stack - it will always override other layers
85
+ The priority order from highest to lowest is:
86
+
87
+ 1. **Your project files** - always have the highest priority
88
+ 2. **Auto-scanned layers** from `~~/layers` directory - sorted alphabetically (Z has higher priority than A)
89
+ 3. **Layers in `extends`** config - first entry has higher priority than second
90
+
91
+ ### When to Use Each
92
+
93
+ - **`extends`** - Use for external dependencies (npm packages, remote repositories) or layers outside your project directory
94
+ - **`~~/layers` directory** - Use for local layers that are part of your project
95
+
96
+ ::tip
97
+ If you need to control the order of auto-scanned layers, you can prefix them with numbers: `~/layers/1.z-layer`, `~/layers/2.a-layer`. This way `2.a-layer` will have higher priority than `1.z-layer`.
98
+ ::
99
+
100
+ ### Example
88
101
 
89
102
  ```ts [nuxt.config.ts]
90
103
  export default defineNuxtConfig({
91
104
  extends: [
92
- // Highest priority (among extends)
105
+ // Local layer outside the project
93
106
  '../base',
94
- // Medium priority
107
+ // NPM package
95
108
  '@my-themes/awesome',
96
- // Lower priority
109
+ // Remote repository
97
110
  'github:my-themes/awesome#v1',
98
111
  ],
99
- // Your project has the highest priority
100
112
  })
101
113
  ```
102
114
 
103
- This means if multiple layers define the same component, configuration, or file, the one with higher priority will be used.
115
+ If you also have `~~/layers/custom`, the priority order is:
116
+ - Your project files (highest)
117
+ - `~~/layers/custom`
118
+ - `../base`
119
+ - `@my-themes/awesome`
120
+ - `github:my-themes/awesome#v1` (lowest)
121
+
122
+ This means your project files will override any layer, and `~~/layers/custom` will override anything in `extends`.
104
123
 
105
124
  ::read-more{to="/docs/guide/going-further/layers"}
106
125
  Read more about layers in the **Layer Author Guide**.
@@ -5,7 +5,7 @@ head.title: "node_modules/"
5
5
  navigation.icon: i-vscode-icons-folder-type-node
6
6
  ---
7
7
 
8
- The package manager ([`npm`](https://docs.npmjs.com/cli/commands/npm) or [`yarn`](https://yarnpkg.com) or [`pnpm`](https://pnpm.io/cli/install) or [`bun`](https://bun.sh/package-manager)) creates this directory to store the dependencies of your project.
8
+ The package manager ([`npm`](https://docs.npmjs.com/cli/commands/npm/) or [`yarn`](https://yarnpkg.com) or [`pnpm`](https://pnpm.io/cli/install) or [`bun`](https://bun.com/package-manager)) creates this directory to store the dependencies of your project.
9
9
 
10
10
  ::important
11
11
  This directory should be added to your [`.gitignore`](/docs/3.x/guide/directory-structure/gitignore) file to avoid pushing the dependencies to your repository.
@@ -22,3 +22,26 @@ As you need to, you can customize the contents of this file. However, it is reco
22
22
  ::note
23
23
  If you need to customize your `paths`, this will override the auto-generated path aliases. Instead, we recommend that you add any path aliases you need to the [`alias`](/docs/3.x/api/nuxt-config#alias) property within your `nuxt.config`, where they will get picked up and added to the auto-generated `tsconfig`.
24
24
  ::
25
+
26
+ ## Extending TypeScript Configuration
27
+
28
+ You can customize the TypeScript configuration of your Nuxt project for each context (`app` and `server`) in the `nuxt.config.ts` file.
29
+ <!-- @case-police-ignore tsConfig -->
30
+ ```ts twoslash [nuxt.config.ts]
31
+ export default defineNuxtConfig({
32
+ typescript: {
33
+ // customize tsconfig.app.json
34
+ tsConfig: {
35
+ // ...
36
+ },
37
+ },
38
+ nitro: {
39
+ typescript: {
40
+ // customize tsconfig.server.json
41
+ tsConfig: {
42
+ // ...
43
+ },
44
+ },
45
+ },
46
+ })
47
+ ```
@@ -8,7 +8,7 @@ description: "Nuxt supports ESLint out of the box"
8
8
  The recommended approach for Nuxt is to enable ESLint support using the [`@nuxt/eslint`](https://eslint.nuxt.com/packages/module) module, that will setup project-aware ESLint configuration for you.
9
9
 
10
10
  :::callout{icon="i-lucide-lightbulb"}
11
- The module is designed for the [new ESLint flat config format](https://eslint.org/docs/latest/use/configure/configuration-files-new) with is the [default format since ESLint v9](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/). If you are using the legacy `.eslintrc` config, you will need to [configure manually with `@nuxt/eslint-config`](https://eslint.nuxt.com/packages/config#legacy-config-format). We highly recommend you to migrate over the flat config to be future-proof.
11
+ The module is designed for the [new ESLint flat config format](https://eslint.org/docs/latest/use/configure/configuration-files-new) which is the [default format since ESLint v9](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/). If you are using the legacy `.eslintrc` config, you will need to [configure manually with `@nuxt/eslint-config`](https://eslint.nuxt.com/packages/config#legacy-config-format). We highly recommend you to migrate over the flat config to be future-proof.
12
12
  :::
13
13
 
14
14
  ## Quick Setup
@@ -397,12 +397,12 @@ should do this automatically for you.)
397
397
  // This would be unsafe in a dynamic page (e.g. `[slug].vue`) because the route slug makes a difference
398
398
  // to the data fetched, but Nuxt can't know that because it's not reflected in the key.
399
399
  const route = useRoute()
400
- const { data } = await useAsyncData(async () => {
401
- return await $fetch(`/api/my-page/${route.params.slug}`)
400
+ const { data } = await useAsyncData(async (_nuxtApp, { signal }) => {
401
+ return await $fetch(`/api/my-page/${route.params.slug}`, { signal })
402
402
  })
403
403
  // Instead, you should use a key that uniquely identifies the data fetched.
404
- const { data } = await useAsyncData(route.params.slug, async () => {
405
- return await $fetch(`/api/my-page/${route.params.slug}`)
404
+ const { data } = await useAsyncData(route.params.slug, async (_nuxtApp, { signal }) => {
405
+ return await $fetch(`/api/my-page/${route.params.slug}`, { signal })
406
406
  })
407
407
  ```
408
408
 
@@ -774,7 +774,7 @@ An example of such a workflow is available on [the module starter](https://githu
774
774
 
775
775
  Having a playground Nuxt application to test your module when developing it is really useful. [The module starter integrates one for that purpose](#how-to-develop).
776
776
 
777
- You can test your module with other Nuxt applications (applications that are not part of your module repository) locally. To do so, you can use [`npm pack`](https://docs.npmjs.com/cli/commands/npm-pack) command, or your package manager equivalent, to create a tarball from your module. Then in your test project, you can add your module to `package.json` packages as: `"my-module": "file:/path/to/tarball.tgz"`.
777
+ You can test your module with other Nuxt applications (applications that are not part of your module repository) locally. To do so, you can use [`npm pack`](https://docs.npmjs.com/cli/commands/npm-pack/) command, or your package manager equivalent, to create a tarball from your module. Then in your test project, you can add your module to `package.json` packages as: `"my-module": "file:/path/to/tarball.tgz"`.
778
778
 
779
779
  After that, you should be able to reference `my-module` like in any regular project.
780
780
 
@@ -68,29 +68,46 @@ Additionally, certain other files in the layer directory will be auto-scanned an
68
68
 
69
69
  ## Layer Priority
70
70
 
71
- When extending from multiple layers, it's important to understand the priority order:
71
+ When extending from multiple layers, it's important to understand the override order. Layers with **higher priority** override layers with lower priority when they define the same files or components.
72
72
 
73
- 1. **Layers in `extends`** - earlier entries have higher priority (first overrides second)
74
- 2. **Auto-scanned local layers** from `~~/layers` directory in alphabetical order (Z overrides A)
75
- 3. **Your project** has the highest priority in the stack - it will always override other layers
73
+ The priority order from highest to lowest is:
76
74
 
77
- For example:
75
+ 1. **Your project files** - always have the highest priority
76
+ 2. **Auto-scanned layers** from `~~/layers` directory - sorted alphabetically (Z has higher priority than A)
77
+ 3. **Layers in `extends`** config - first entry has higher priority than second
78
+
79
+ ### When to Use Each
80
+
81
+ - **`extends`** - Use for external dependencies (npm packages, remote repositories) or layers outside your project directory
82
+ - **`~~/layers` directory** - Use for local layers that are part of your project
83
+
84
+ ::tip
85
+ If you need to control the order of auto-scanned layers, you can prefix them with numbers: `~/layers/1.z-layer`, `~/layers/2.a-layer`. This way `2.a-layer` will have higher priority than `1.z-layer`.
86
+ ::
87
+
88
+ ### Example
78
89
 
79
90
  ```ts [nuxt.config.ts]
80
91
  export default defineNuxtConfig({
81
92
  extends: [
82
- // Highest priority (among extends)
83
- './layers/base',
84
- // Medium priority
85
- './layers/theme',
86
- // Lower priority
87
- './layers/custom',
93
+ // Local layer outside the project
94
+ '../base',
95
+ // NPM package
96
+ '@my-themes/awesome',
97
+ // Remote repository
98
+ 'github:my-themes/awesome#v1',
88
99
  ],
89
- // Your project has the highest priority
90
100
  })
91
101
  ```
92
102
 
93
- If you also have auto-scanned layers like `~~/layers/a` and `~~/layers/z`, the complete override order would be: `base` > `theme` > `custom` > `z` > `a` > your project.
103
+ If you also have `~~/layers/custom`, the priority order is:
104
+ - Your project files (highest)
105
+ - `~~/layers/custom`
106
+ - `../base`
107
+ - `@my-themes/awesome`
108
+ - `github:my-themes/awesome#v1` (lowest)
109
+
110
+ This means your project files will override any layer, and `~~/layers/custom` will override anything in `extends`.
94
111
 
95
112
  ## Starter Template
96
113
 
@@ -66,7 +66,7 @@ import config from '~/data/hello.yaml'
66
66
 
67
67
  ## Using Vite Plugins in Nuxt Modules
68
68
 
69
- If you're developing a Nuxt module and need to add Vite plugins, you should use the [`addVitePlugin`](/docs/4.x/api/kit/builder#addviteplugin) utility:
69
+ If you're developing a Nuxt module and need to add Vite plugins, you should use the [`addVitePlugin`](/docs/3.x/api/kit/builder#addviteplugin) utility:
70
70
 
71
71
  ```ts [modules/my-module.ts]
72
72
  import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
@@ -101,6 +101,6 @@ export default defineNuxtModule({
101
101
  If you're writing code that needs to access resolved Vite configuration, you should use the `config` and `configResolved` hooks _within_ your Vite plugin, rather than using Nuxt's `vite:extend`, `vite:extendConfig` and `vite:configResolved`.
102
102
  ::
103
103
 
104
- ::read-more{to="/docs/4.x/api/kit/builder#addviteplugin"}
104
+ ::read-more{to="/docs/3.x/api/kit/builder#addviteplugin"}
105
105
  Read more about `addVitePlugin` in the Nuxt Kit documentation.
106
106
  ::
@@ -18,9 +18,9 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
18
18
 
19
19
  ```vue [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/3.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/3.x/api/composables/use-async-data).
75
134
  ::
@@ -116,7 +175,7 @@ You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `u
116
175
 
117
176
  ### Shared State and Option Consistency
118
177
 
119
- 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.
120
179
 
121
180
  The following options **must be consistent** across all calls with the same key:
122
181
  - `handler` function
@@ -135,12 +194,12 @@ The following options **can differ** without triggering warnings:
135
194
 
136
195
  ```ts
137
196
  // ❌ This will trigger a development warning
138
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
139
- 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 })
140
199
 
141
200
  // ✅ This is allowed
142
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
143
- 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 })
144
203
  ```
145
204
 
146
205
  ::tip
@@ -159,6 +218,7 @@ Keyed state created using `useAsyncData` can be retrieved across your Nuxt appli
159
218
  - `pending`: the request is in progress
160
219
  - `success`: the request has completed successfully
161
220
  - `error`: the request has failed
221
+ - `pending`: a `Ref<boolean>` that is `true` while the request is in progress.
162
222
  - `clear`: a function that can be used to set `data` to `undefined` (or the value of `options.default()` if provided), set `error` to `null`, set `status` to `idle`, and mark any currently pending requests as cancelled.
163
223
 
164
224
  By default, Nuxt waits until a `refresh` is finished before it can be executed again.
@@ -170,14 +230,16 @@ If you have not fetched data on the server (for example, with `server: false`),
170
230
  ## Type
171
231
 
172
232
  ```ts [Signature]
233
+ export type AsyncDataHandler<ResT> = (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<ResT>
234
+
173
235
  export function useAsyncData<DataT, DataE> (
174
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
175
- options?: AsyncDataOptions<DataT>
236
+ handler: AsyncDataHandler<DataT>,
237
+ options?: AsyncDataOptions<DataT>,
176
238
  ): AsyncData<DataT, DataE>
177
239
  export function useAsyncData<DataT, DataE> (
178
240
  key: MaybeRefOrGetter<string>,
179
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
180
- options?: AsyncDataOptions<DataT>
241
+ handler: AsyncDataHandler<DataT>,
242
+ options?: AsyncDataOptions<DataT>,
181
243
  ): Promise<AsyncData<DataT, DataE>>
182
244
 
183
245
  type AsyncDataOptions<DataT> = {
@@ -206,6 +268,7 @@ type AsyncData<DataT, ErrorT> = {
206
268
  clear: () => void
207
269
  error: Ref<ErrorT | null>
208
270
  status: Ref<AsyncDataRequestStatus>
271
+ pending: Ref<boolean>
209
272
  }
210
273
 
211
274
  interface AsyncDataExecuteOptions {
@@ -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
 
@@ -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> = {
@@ -8,28 +8,12 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/3.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/3.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/3.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/3.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/3.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/3.x/api/composables/use-head-safe).
11
+ ## Usage
12
12
 
13
- :read-more{to="/docs/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/3.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
-
21
- Below are the non-reactive types for [`useHead`](/docs/3.x/api/composables/use-head) .
22
42
 
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
83
+
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
+ ```
43
168
 
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>`
169
+ :read-more{to="/docs/3.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/3.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.
@@ -8,15 +8,68 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- ## Description
12
-
13
- By default, [`useAsyncData`](/docs/3.x/api/composables/use-async-data) blocks navigation until its async handler is resolved. `useLazyAsyncData` provides a wrapper around [`useAsyncData`](/docs/3.x/api/composables/use-async-data) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`.
11
+ `useLazyAsyncData` provides a wrapper around [`useAsyncData`](/docs/3.x/api/composables/use-async-data) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`.
14
12
 
15
13
  ::note
16
- `useLazyAsyncData` has the same signature as [`useAsyncData`](/docs/3.x/api/composables/use-async-data).
14
+ By default, [`useAsyncData`](/docs/3.x/api/composables/use-async-data) blocks navigation until its async handler is resolved. `useLazyAsyncData` allows navigation to occur immediately while data fetching continues in the background.
15
+ ::
16
+
17
+ ## Usage
18
+
19
+ ```vue [app/pages/index.vue]
20
+ <script setup lang="ts">
21
+ const { status, data: posts } = await useLazyAsyncData('posts', () => $fetch('/api/posts'))
22
+ </script>
23
+
24
+ <template>
25
+ <div>
26
+ <div v-if="status === 'pending'">
27
+ Loading...
28
+ </div>
29
+ <div v-else-if="status === 'error'">
30
+ Error loading posts
31
+ </div>
32
+ <div v-else>
33
+ {{ posts }}
34
+ </div>
35
+ </div>
36
+ </template>
37
+ ```
38
+
39
+ When using `useLazyAsyncData`, navigation will occur before fetching is complete. This means you must handle `pending` and `error` states directly within your component's template.
40
+
41
+ ::warning
42
+ `useLazyAsyncData` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyAsyncData`.
17
43
  ::
18
44
 
19
- :read-more{to="/docs/api/composables/use-async-data"}
45
+ ## Type
46
+
47
+ ```ts [Signature]
48
+ export function useLazyAsyncData<DataT, ErrorT> (
49
+ handler: (ctx?: NuxtApp) => Promise<DataT>,
50
+ options?: AsyncDataOptions<DataT>,
51
+ ): AsyncData<DataT, ErrorT>
52
+
53
+ export function useLazyAsyncData<DataT, ErrorT> (
54
+ key: string,
55
+ handler: (ctx?: NuxtApp) => Promise<DataT>,
56
+ options?: AsyncDataOptions<DataT>,
57
+ ): AsyncData<DataT, ErrorT>
58
+ ```
59
+
60
+ `useLazyAsyncData` has the same signature as [`useAsyncData`](/docs/3.x/api/composables/use-async-data).
61
+
62
+ ## Parameters
63
+
64
+ `useLazyAsyncData` accepts the same parameters as [`useAsyncData`](/docs/3.x/api/composables/use-async-data), with the `lazy` option automatically set to `true`.
65
+
66
+ :read-more{to="/docs/3.x/api/composables/use-async-data#parameters"}
67
+
68
+ ## Return Values
69
+
70
+ `useLazyAsyncData` returns the same values as [`useAsyncData`](/docs/3.x/api/composables/use-async-data).
71
+
72
+ :read-more{to="/docs/3.x/api/composables/use-async-data#return-values"}
20
73
 
21
74
  ## Example
22
75
 
@@ -40,8 +93,4 @@ watch(count, (newCount) => {
40
93
  </template>
41
94
  ```
42
95
 
43
- ::warning
44
- `useLazyAsyncData` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyAsyncData`.
45
- ::
46
-
47
- :read-more{to="/docs/getting-started/data-fetching"}
96
+ :read-more{to="/docs/3.x/getting-started/data-fetching"}
@@ -8,21 +8,81 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- ## Description
11
+ `useLazyFetch` provides a wrapper around [`useFetch`](/docs/3.x/api/composables/use-fetch) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`.
12
12
 
13
- By default, [`useFetch`](/docs/3.x/api/composables/use-fetch) blocks navigation until its async handler is resolved. `useLazyFetch` provides a wrapper around [`useFetch`](/docs/3.x/api/composables/use-fetch) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`.
13
+ ## Usage
14
+
15
+ By default, [`useFetch`](/docs/3.x/api/composables/use-fetch) blocks navigation until its async handler is resolved. `useLazyFetch` allows navigation to proceed immediately, with data being fetched in the background.
16
+
17
+ ```vue [app/pages/index.vue]
18
+ <script setup lang="ts">
19
+ const { status, data: posts } = await useLazyFetch('/api/posts')
20
+ </script>
21
+
22
+ <template>
23
+ <div v-if="status === 'pending'">
24
+ Loading ...
25
+ </div>
26
+ <div v-else>
27
+ <div v-for="post in posts">
28
+ <!-- do something -->
29
+ </div>
30
+ </div>
31
+ </template>
32
+ ```
14
33
 
15
34
  ::note
16
35
  `useLazyFetch` has the same signature as [`useFetch`](/docs/3.x/api/composables/use-fetch).
17
36
  ::
18
37
 
38
+ ::warning
39
+ Awaiting `useLazyFetch` only ensures the call is initialized. On client-side navigation, data may not be immediately available, and you must handle the `pending` state in your component's template.
40
+ ::
41
+
42
+ ::warning
43
+ `useLazyFetch` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyFetch`.
44
+ ::
45
+
46
+ ## Type
47
+
48
+ ```ts [Signature]
49
+ export function useLazyFetch<DataT, ErrorT> (
50
+ url: string | Request | Ref<string | Request> | (() => string | Request),
51
+ options?: UseFetchOptions<DataT>,
52
+ ): Promise<AsyncData<DataT, ErrorT>>
53
+ ```
54
+
19
55
  ::note
20
- Awaiting `useLazyFetch` in this mode only ensures the call is initialized. On client-side navigation, data may not be immediately available, and you should make sure to handle the pending state in your app.
56
+ `useLazyFetch` is equivalent to `useFetch` with `lazy: true` option set. See [`useFetch`](/docs/3.x/api/composables/use-fetch) for full type definitions.
21
57
  ::
22
58
 
23
- :read-more{to="/docs/api/composables/use-fetch"}
59
+ ## Parameters
60
+
61
+ `useLazyFetch` accepts the same parameters as [`useFetch`](/docs/3.x/api/composables/use-fetch):
62
+
63
+ - `URL` (`string | Request | Ref<string | Request> | () => string | Request`): The URL or request to fetch.
64
+ - `options` (object): Same as [`useFetch` options](/docs/3.x/api/composables/use-fetch#parameters), with `lazy` automatically set to `true`.
65
+
66
+ :read-more{to="/docs/3.x/api/composables/use-fetch#parameters"}
24
67
 
25
- ## Example
68
+ ## Return Values
69
+
70
+ Returns the same `AsyncData` object as [`useFetch`](/docs/3.x/api/composables/use-fetch):
71
+
72
+ | Name | Type | Description |
73
+ | --- | --- |--- |
74
+ | `data` | `Ref<DataT \| undefined>` | The result of the asynchronous fetch. |
75
+ | `refresh` | `(opts?: AsyncDataExecuteOptions) => Promise<void>` | Function to manually refresh the data. |
76
+ | `execute` | `(opts?: AsyncDataExecuteOptions) => Promise<void>` | Alias for `refresh`. |
77
+ | `error` | `Ref<ErrorT \| undefined>` | Error object if the data fetching failed. |
78
+ | `status` | `Ref<'idle' \| 'pending' \| 'success' \| 'error'>` | Status of the data request. |
79
+ | `clear` | `() => void` | Resets `data` to `undefined`, `error` to `undefined`, sets `status` to `idle`, and cancels any pending requests. |
80
+
81
+ :read-more{to="/docs/3.x/api/composables/use-fetch#return-values"}
82
+
83
+ ## Examples
84
+
85
+ ### Handling Pending State
26
86
 
27
87
  ```vue [pages/index.vue]
28
88
  <script setup lang="ts">
@@ -48,8 +108,4 @@ watch(posts, (newPosts) => {
48
108
  </template>
49
109
  ```
50
110
 
51
- ::note
52
- `useLazyFetch` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyFetch`.
53
- ::
54
-
55
- :read-more{to="/docs/getting-started/data-fetching"}
111
+ :read-more{to="/docs/3.x/getting-started/data-fetching"}
@@ -108,7 +108,7 @@ Nuxt exposes the following properties through `ssrContext`:
108
108
  ::code-group
109
109
  ```vue [app.vue]
110
110
  <script setup lang="ts">
111
- const { data } = await useAsyncData('count', () => $fetch('/api/count'))
111
+ const { data } = await useAsyncData('count', (_nuxtApp, { signal }) => $fetch('/api/count', { signal }))
112
112
  </script>
113
113
  ```
114
114
  ```ts [server/api/count.ts]
@@ -67,7 +67,7 @@ Optimistic Updates is a technique where the user interface is updated immediatel
67
67
  ```vue [pages/todos.vue]
68
68
  <script setup lang="ts">
69
69
  // We can access same data later using 'todos' key
70
- const { data } = await useAsyncData('todos', () => $fetch('/api/todos'))
70
+ const { data } = await useAsyncData('todos', (_nuxtApp, { signal }) => $fetch('/api/todos', { signal }))
71
71
  </script>
72
72
  ```
73
73
 
@@ -33,7 +33,7 @@ const { data: forwarded } = await useAsyncData(() => requestFetch('/api/cookies'
33
33
 
34
34
  // This will NOT forward anything
35
35
  // Result: { cookies: {} }
36
- const { data: notForwarded } = await useAsyncData(() => $fetch('/api/cookies'))
36
+ const { data: notForwarded } = await useAsyncData((_nuxtApp, { signal }) => $fetch('/api/cookies', { signal }))
37
37
  </script>
38
38
  ```
39
39
 
@@ -76,7 +76,7 @@ The `useRoute()` composable should only be used in the setup function of a Vue c
76
76
  This applies to any composable that uses `useRoute()` internally too.
77
77
  ::
78
78
 
79
- ::read-more{to="/docs/4.x/guide/directory-structure/app/middleware"}
79
+ ::read-more{to="/docs/3.x/guide/directory-structure/app/middleware"}
80
80
  Read more about accessing the route in the middleware section.
81
81
  ::
82
82
 
@@ -15,7 +15,7 @@ This composable is available in Nuxt v3.14+.
15
15
  ```ts [signature]
16
16
  function useRuntimeHook<THookName extends keyof RuntimeNuxtHooks> (
17
17
  name: THookName,
18
- fn: RuntimeNuxtHooks[THookName] extends HookCallback ? RuntimeNuxtHooks[THookName] : never
18
+ fn: RuntimeNuxtHooks[THookName] extends HookCallback ? RuntimeNuxtHooks[THookName] : never,
19
19
  ): void
20
20
  ```
21
21
 
@@ -119,7 +119,7 @@ await navigateTo('https://nuxt.com', {
119
119
  ```ts [Signature]
120
120
  export function navigateTo (
121
121
  to: RouteLocationRaw | undefined | null,
122
- options?: NavigateToOptions
122
+ options?: NavigateToOptions,
123
123
  ): Promise<void | NavigationFailure | false> | false | void | RouteLocationRaw
124
124
 
125
125
  interface NavigateToOptions {
@@ -35,8 +35,8 @@ const loggedIn = computed(() => !!tokenCookie.value)
35
35
  </script>
36
36
  ```
37
37
 
38
- ::note{to="/docs/guide/going-further/experimental-features#cookiestore"}
39
- You can enable experimental `cookieStore` option to automatically refresh `useCookie` value when cookie changes in the browser.
38
+ ::note{to="/docs/3.x/guide/going-further/experimental-features#cookiestore"}
39
+ Since [Nuxt v3.12.0](https://github.com/nuxt/nuxt/releases/tag/v3.12.0), the experimental `cookieStore` option is enabled by default. It automatically refreshes the `useCookie` value when cookies change in the browser.
40
40
  ::
41
41
 
42
42
  ## Type
@@ -47,7 +47,7 @@ export function defineNuxtModule<TOptions extends ModuleOptions> (
47
47
 
48
48
  export function defineNuxtModule<TOptions extends ModuleOptions> (): {
49
49
  with: <TOptionsDefaults extends Partial<TOptions>> (
50
- definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>
50
+ definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>,
51
51
  ) => NuxtModule<TOptions, TOptionsDefaults, true>
52
52
  }
53
53
  ```
@@ -8,7 +8,7 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- Programmatic usage can be helpful when you want to use Nuxt programmatically, for example, when building a [CLI tool](https://github.com/nuxt/cli) or [test utils](https://github.com/nuxt/nuxt/tree/main/packages/test-utils).
11
+ Programmatic usage can be helpful when you want to use Nuxt programmatically, for example, when building a [CLI tool](https://github.com/nuxt/cli) or [test utils](https://github.com/nuxt/test-utils).
12
12
 
13
13
  ## `loadNuxt`
14
14
 
@@ -31,7 +31,7 @@ function loadNuxt (loadOptions?: LoadNuxtOptions): Promise<Nuxt>
31
31
 
32
32
  ## `buildNuxt`
33
33
 
34
- Build Nuxt programmatically. It will invoke the builder (currently [@nuxt/vite-builder](https://github.com/nuxt/nuxt/tree/main/packages/vite) or [@nuxt/webpack-builder](https://github.com/nuxt/nuxt/tree/main/packages/webpack)) to bundle the application.
34
+ Build Nuxt programmatically. It will invoke the builder (currently [@nuxt/vite-builder](https://github.com/nuxt/nuxt/blob/main/packages/vite) or [@nuxt/webpack-builder](https://github.com/nuxt/nuxt/blob/main/packages/webpack)) to bundle the application.
35
35
 
36
36
  ### Type
37
37
 
@@ -113,7 +113,7 @@ function addComponent (options: AddComponentOptions): void
113
113
  | ------------------ | ---------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
114
114
  | `name` | `string` | `true` | Component name. |
115
115
  | `filePath` | `string` | `true` | Path to the component. |
116
- | `declarationPath` | `string` | `false` | Path to component's declaration file. It is used to generate components' [type templates](/docs/4.x/api/kit/templates#addtypetemplate); if not provided, `filePath` is used instead. |
116
+ | `declarationPath` | `string` | `false` | Path to component's declaration file. It is used to generate components' [type templates](/docs/3.x/api/kit/templates#addtypetemplate); if not provided, `filePath` is used instead. |
117
117
  | `pascalName` | `string` | `false` | Pascal case component name. If not provided, it will be generated from the component name. |
118
118
  | `kebabName` | `string` | `false` | Kebab case component name. If not provided, it will be generated from the component name. |
119
119
  | `export` | `string` | `false` | Specify named or default export. If not provided, it will be set to `'default'`. |
@@ -39,7 +39,7 @@ If your issue concerns Vue or Vite, please try to reproduce it first with the Vu
39
39
 
40
40
  ::card-group
41
41
  :card{title="Vue SSR on StackBlitz" icon="i-simple-icons-stackblitz" to="https://stackblitz.com/github/nuxt-contrib/vue3-ssr-starter/tree/main?terminal=dev" target="_blank"}
42
- :card{title="Vue SSR on CodeSandbox" icon="i-simple-icons-codesandbox" to="https://codesandbox.io/s/github/nuxt-contrib/vue3-ssr-starter/main" target="_blank"}
42
+ :card{title="Vue SSR on CodeSandbox" icon="i-simple-icons-codesandbox" to="https://codesandbox.io/p/sandbox/github/nuxt-contrib/vue3-ssr-starter/main" target="_blank"}
43
43
  :card{title="Vue SSR Template on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt-contrib/vue3-ssr-starter/generate" target="_blank"}
44
44
  ::
45
45
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/docs",
3
- "version": "3.20.0",
3
+ "version": "3.20.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",