@nuxt/docs-nightly 4.4.0-29550724.be97f20e → 4.4.0-29551604.0a8a57da

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.
@@ -300,6 +300,10 @@ it('can also mount an app', async () => {
300
300
  })
301
301
  ```
302
302
 
303
+ The options object accepts `@vue/test-utils` mount options and the following properties:
304
+
305
+ - `route`: the initial route, or `false` to skip the initial route change (default `/`).
306
+
303
307
  #### `renderSuspended`
304
308
 
305
309
  `renderSuspended` allows you to render any Vue component within the Nuxt environment using `@testing-library/vue`, allowing async setup and access to injections from your Nuxt plugins.
@@ -352,14 +356,18 @@ it('can also render an app', async () => {
352
356
  })
353
357
  ```
354
358
 
359
+ The options object accepts `@testing-library/vue` render options and the following properties:
360
+
361
+ - `route`: the initial route, or `false` to skip the initial route change (default `/`).
362
+
355
363
  #### `mockNuxtImport`
356
364
 
357
- `mockNuxtImport` allows you to mock Nuxt's auto import functionality. For example, to mock `useStorage`, you can do so like this:
365
+ `mockNuxtImport` allows you to mock Nuxt's auto import functionality. For example, to mock `useState`, you can do so like this:
358
366
 
359
367
  ```ts twoslash
360
368
  import { mockNuxtImport } from '@nuxt/test-utils/runtime'
361
369
 
362
- mockNuxtImport('useStorage', () => {
370
+ mockNuxtImport('useState', () => {
363
371
  return () => {
364
372
  return { value: 'mocked storage' }
365
373
  }
@@ -368,6 +376,27 @@ mockNuxtImport('useStorage', () => {
368
376
  // your tests here
369
377
  ```
370
378
 
379
+ You can explicitly type the mock for type safety, and use the original implementation passed to the factory function when mocking complex functionality.
380
+
381
+ ```ts twoslash [test/nuxt/import.test.ts]
382
+ import { mockNuxtImport } from '@nuxt/test-utils/runtime'
383
+
384
+ mockNuxtImport<typeof useState>('useState', (original) => {
385
+ return (...args) => {
386
+ return { ...original('some-key'), value: 'mocked state' }
387
+ }
388
+ })
389
+
390
+ // or specify the target to mock
391
+ mockNuxtImport(useState, (original) => {
392
+ return (...args) => {
393
+ return { ...original('some-key'), value: 'mocked state' }
394
+ }
395
+ })
396
+
397
+ // your tests here
398
+ ```
399
+
371
400
  ::note
372
401
  `mockNuxtImport` can only be used once per mocked import per test file. It is actually a macro that gets transformed to `vi.mock` and `vi.mock` is hoisted, as described [in the Vitest docs](https://vitest.dev/api/vi#vi-mock).
373
402
  ::
@@ -378,24 +407,43 @@ If you need to mock a Nuxt import and provide different implementations between
378
407
  import { vi } from 'vitest'
379
408
  import { mockNuxtImport } from '@nuxt/test-utils/runtime'
380
409
 
381
- const { useStorageMock } = vi.hoisted(() => {
410
+ const { useStateMock } = vi.hoisted(() => {
382
411
  return {
383
- useStorageMock: vi.fn(() => {
412
+ useStateMock: vi.fn(() => {
384
413
  return { value: 'mocked storage' }
385
414
  }),
386
415
  }
387
416
  })
388
417
 
389
- mockNuxtImport('useStorage', () => {
390
- return useStorageMock
418
+ mockNuxtImport('useState', () => {
419
+ return useStateMock
391
420
  })
392
421
 
393
422
  // Then, inside a test
394
- useStorageMock.mockImplementation(() => {
423
+ useStateMock.mockImplementation(() => {
395
424
  return { value: 'something else' }
396
425
  })
397
426
  ```
398
427
 
428
+ If you need to mock behavior only inside a test, you can also use the following approach.
429
+
430
+ ```ts twoslash
431
+ import { beforeEach, vi } from 'vitest'
432
+ import { mockNuxtImport } from '@nuxt/test-utils/runtime'
433
+
434
+ mockNuxtImport(useRoute, original => vi.fn(original))
435
+
436
+ beforeEach(() => {
437
+ vi.resetAllMocks()
438
+ })
439
+
440
+ // Then, inside a test
441
+ const useRouteOriginal = vi.mocked(useRoute).getMockImplementation()!
442
+ vi.mocked(useRoute).mockImplementation(
443
+ (...args) => ({ ...useRouteOriginal(...args), path: '/mocked' }),
444
+ )
445
+ ```
446
+
399
447
  #### `mockComponent`
400
448
 
401
449
  `mockComponent` allows you to mock Nuxt's component.
@@ -477,6 +525,12 @@ registerEndpoint('/test/', {
477
525
  })
478
526
  ```
479
527
 
528
+ This object accepts the following properties:
529
+
530
+ - `handler`: the event handler function
531
+ - `method`: (optional) HTTP method to match (e.g., 'GET', 'POST')
532
+ - `once`: (optional) if true, the handler will only be used for the first matching request and then automatically removed
533
+
480
534
  > **Note**: If your requests in a component go to an external API, you can use `baseURL` and then make it empty using [Nuxt Environment Override Config](/docs/4.x/getting-started/configuration#environment-overrides) (`$test`) so all your requests will go to Nitro server.
481
535
 
482
536
  #### Conflict with End-To-End Testing
@@ -490,7 +544,7 @@ If you would like to use both the end-to-end and unit testing functionality of `
490
544
  ```ts twoslash
491
545
  import { mockNuxtImport } from '@nuxt/test-utils/runtime'
492
546
 
493
- mockNuxtImport('useStorage', () => {
547
+ mockNuxtImport('useState', () => {
494
548
  return () => {
495
549
  return { value: 'mocked storage' }
496
550
  }
@@ -61,6 +61,7 @@ When you set your `future.compatibilityVersion` to `5`, defaults throughout your
61
61
  - **Vite Environment API**: Automatically enables the new [Vite Environment API](/docs/4.x/getting-started/upgrade#migration-to-vite-environment-api) for improved build configuration
62
62
  - **Normalized Page Names**: Page component names will [match their route names](/docs/4.x/getting-started/upgrade#normalized-page-component-names) for consistent `<KeepAlive>` behavior
63
63
  - **`clearNuxtState` resets to defaults**: `clearNuxtState` will [reset state to its initial value](/docs/4.x/getting-started/upgrade#respect-defaults-when-clearing-usestate) instead of setting it to `undefined`
64
+ - **Non-async `callHook`**: [`callHook` may return `void`](/docs/4.x/getting-started/upgrade#non-async-callhook) instead of always returning a `Promise`
64
65
  - Other Nuxt 5 improvements and changes as they become available
65
66
 
66
67
  ::note
@@ -180,6 +181,52 @@ addVitePlugin(() => ({
180
181
  Learn more about Vite's Environment API
181
182
  ::
182
183
 
184
+ ### Non-Async `callHook`
185
+
186
+ 🚦 **Impact Level**: Minimal
187
+
188
+ #### What Changed
189
+
190
+ With the upgrade to [hookable v6](https://github.com/unjs/hookable), `callHook` may now return `void` instead of always returning `Promise<void>`. This is a significant performance improvement that avoids unnecessary `Promise` allocations when there are no registered hooks or all hooks are synchronous.
191
+
192
+ By default (with `compatibilityVersion: 4`), Nuxt wraps `callHook` with `Promise.resolve()` so that existing `.then()` and `.catch()` chaining continues to work. With `compatibilityVersion: 5`, this wrapper is removed.
193
+
194
+ ::tip
195
+ This affects both build-time Nuxt hooks (used by Nuxt modules) and runtime Nuxt hooks (which you might use in your application code).
196
+ ::
197
+
198
+ #### Reasons for Change
199
+
200
+ Hookable v6's `callHook` is 20-40x faster because it avoids creating a `Promise` when one is not needed. This benefits applications with many hook call sites.
201
+
202
+ #### Migration Steps
203
+
204
+ If you or your modules use `callHook` with `.then()` or `.catch()` chaining, switch to `await`:
205
+
206
+ ```diff
207
+ - nuxtApp.callHook('my:hook', data).then(() => { ... })
208
+ + await nuxtApp.callHook('my:hook', data)
209
+ ```
210
+
211
+ ```diff
212
+ - nuxtApp.hooks.callHook('my:hook', data).catch(err => { ... })
213
+ + try { await nuxtApp.hooks.callHook('my:hook', data) } catch (err) { ... }
214
+ ```
215
+
216
+ ::tip
217
+ You can test this feature early by setting `future.compatibilityVersion: 5` (see [Testing Nuxt 5](/docs/4.x/getting-started/upgrade#testing-nuxt-5)) or by enabling it explicitly with `experimental.asyncCallHook: false`.
218
+ ::
219
+
220
+ Alternatively, you can ensure `callHook` always returns a `Promise` with:
221
+
222
+ ```ts twoslash [nuxt.config.ts]
223
+ export default defineNuxtConfig({
224
+ experimental: {
225
+ asyncCallHook: true,
226
+ },
227
+ })
228
+ ```
229
+
183
230
  ## Migrating to Nuxt 4
184
231
 
185
232
  Nuxt 4 includes significant improvements and changes. This guide will help you migrate your existing Nuxt 3 application to Nuxt 4.
@@ -122,7 +122,7 @@ File | Layout Name
122
122
 
123
123
  You can also use the [`setPageLayout`](/docs/4.x/api/utils/set-page-layout) helper to change the layout dynamically:
124
124
 
125
- ```vue twoslash
125
+ ```vue twoslash [app/pages/index.vue]
126
126
  <script setup lang="ts">
127
127
  declare module 'nuxt/app' {
128
128
  interface NuxtLayouts {
@@ -6,32 +6,32 @@ description: Why fixing hydration issues is important
6
6
 
7
7
  When developing, you may face hydration issues. Don't ignore those warnings.
8
8
 
9
- # Why is it important to fix them?
9
+ ## Why is it important to fix them?
10
10
 
11
11
  Hydration mismatches are not just warnings - they are indicators of serious problems that can break your application:
12
12
 
13
- ## Performance Impact
13
+ ### Performance Impact
14
14
 
15
15
  - **Increased time to interactive**: Hydration errors force Vue to re-render the entire component tree, which will increase the time for your Nuxt app to become interactive
16
16
  - **Poor user experience**: Users may see content flashing or unexpected layout shifts
17
17
 
18
- ## Functionality Issues
18
+ ### Functionality Issues
19
19
 
20
20
  - **Broken interactivity**: Event listeners may not attach properly, leaving buttons and forms non-functional
21
21
  - **State inconsistencies**: Application state can become out of sync between what the user sees and what the application thinks is rendered
22
22
  - **SEO problems**: Search engines may index different content than what users actually see
23
23
 
24
- # How to detect them
24
+ ## How to detect them
25
25
 
26
- ## Development Console Warnings
26
+ ### Development Console Warnings
27
27
 
28
28
  Vue will log hydration mismatch warnings in the browser console during development:
29
29
 
30
30
  ![Screenshot of Vue hydration mismatch warning in the browser console](/assets/docs/best-practices/vue-console-hydration.png)
31
31
 
32
- # Common reasons
32
+ ## Common reasons
33
33
 
34
- ## Browser-only APIs in Server Context
34
+ ### Browser-only APIs in Server Context
35
35
 
36
36
  **Problem**: Using browser-specific APIs during server-side rendering.
37
37
 
@@ -60,7 +60,7 @@ const userTheme = useCookie('theme', { default: () => 'light' })
60
60
  </script>
61
61
  ```
62
62
 
63
- ## Inconsistent Data
63
+ ### Inconsistent Data
64
64
 
65
65
  **Problem**: Different data between server and client.
66
66
 
@@ -82,7 +82,7 @@ const state = useState('random', () => Math.random())
82
82
  </script>
83
83
  ```
84
84
 
85
- ## Conditional Rendering Based on Client State
85
+ ### Conditional Rendering Based on Client State
86
86
 
87
87
  **Problem**: Using client-only conditions during SSR.
88
88
 
@@ -105,7 +105,7 @@ const state = useState('random', () => Math.random())
105
105
  </template>
106
106
  ```
107
107
 
108
- ## Third-party Libraries with Side Effects
108
+ ### Third-party Libraries with Side Effects
109
109
 
110
110
  **Problem**: Libraries that modify the DOM or have browser dependencies (this happens a LOT with tag managers).
111
111
 
@@ -129,7 +129,7 @@ onMounted(async () => {
129
129
  </script>
130
130
  ```
131
131
 
132
- ## Dynamic Content Based on Time
132
+ ### Dynamic Content Based on Time
133
133
 
134
134
  **Problem**: Content that changes based on current time.
135
135
 
@@ -238,12 +238,19 @@ export default defineNuxtConfig({
238
238
 
239
239
  ## payloadExtraction
240
240
 
241
- Enables extraction of payloads of pages generated with `nuxt generate`.
241
+ Controls how payload data is delivered for prerendered and cached (ISR/SWR) pages.
242
+
243
+ - `'client'` - Payload is inlined in HTML for the initial server render, and extracted to `_payload.json` files for client-side navigation. This avoids a separate network request on initial load while still enabling efficient client-side navigation.
244
+ - `true` - Payload is extracted to a separate `_payload.json` file for both the initial server render and client-side navigation.
245
+ - `false` - Payload extraction is disabled entirely. Payload is always inlined in HTML and no `_payload.json` files are generated.
246
+
247
+ The default is `true`, or `'client'` when `compatibilityVersion: 5` is set.
242
248
 
243
249
  ```ts twoslash [nuxt.config.ts]
244
250
  export default defineNuxtConfig({
245
251
  experimental: {
246
- payloadExtraction: true,
252
+ // Inline payload in HTML, extract for client-side navigation only
253
+ payloadExtraction: 'client',
247
254
  },
248
255
  })
249
256
  ```
@@ -253,7 +260,7 @@ Payload extraction also works for routes using ISR (Incremental Static Regenerat
253
260
  ```ts twoslash [nuxt.config.ts]
254
261
  export default defineNuxtConfig({
255
262
  experimental: {
256
- payloadExtraction: true,
263
+ payloadExtraction: 'client',
257
264
  },
258
265
  routeRules: {
259
266
  // Payload files will be generated for these cached routes
@@ -766,7 +773,9 @@ export default defineNuxtConfig({
766
773
 
767
774
  ## decorators
768
775
 
769
- This option enables enabling decorator syntax across your entire Nuxt/Nitro app, powered by [esbuild](https://github.com/evanw/esbuild/releases/tag/v0.21.3).
776
+ This option enables decorator syntax across your entire Nuxt/Nitro app.
777
+
778
+ When using the Vite builder (default), decorators are lowered via [Babel](https://babeljs.io/) using [`@babel/plugin-proposal-decorators`](https://babeljs.io/docs/babel-plugin-proposal-decorators). When using the webpack or rspack builders, decorators are lowered via [esbuild](https://github.com/evanw/esbuild/releases/tag/v0.21.3).
770
779
 
771
780
  For a long time, TypeScript has had support for decorators via `compilerOptions.experimentalDecorators`. This implementation predated the TC39 standardization process. Now, decorators are a [Stage 3 Proposal](https://github.com/tc39/proposal-decorators), and supported without special configuration in TS 5.0+ (see https://github.com/microsoft/TypeScript/pull/52582 and https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#decorators).
772
781
 
@@ -786,6 +795,24 @@ export default defineNuxtConfig({
786
795
  })
787
796
  ```
788
797
 
798
+ When using the Vite builder or the Nitro server build, you will need to install additional Babel packages as dev dependencies:
799
+
800
+ ::code-group
801
+ ```bash [npm]
802
+ npm install -D @babel/plugin-proposal-decorators @babel/plugin-syntax-jsx
803
+ ```
804
+ ```bash [pnpm]
805
+ pnpm add -D @babel/plugin-proposal-decorators @babel/plugin-syntax-jsx
806
+ ```
807
+ ```bash [yarn]
808
+ yarn add -D @babel/plugin-proposal-decorators @babel/plugin-syntax-jsx
809
+ ```
810
+ ::
811
+
812
+ ::tip
813
+ Nuxt will prompt you to install these automatically if they are not already present.
814
+ ::
815
+
789
816
  ```ts [app/app.vue]
790
817
  function something (_method: () => unknown) {
791
818
  return () => 'decorated'
@@ -161,6 +161,7 @@ type AsyncDataRequestContext = {
161
161
 
162
162
  type AsyncData<DataT, ErrorT> = {
163
163
  data: Ref<DataT | undefined>
164
+ pending: Ref<boolean>
164
165
  refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
165
166
  execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
166
167
  clear: () => void
@@ -229,6 +230,7 @@ This only caches data when `experimental.payloadExtraction` in `nuxt.config` is
229
230
  | `execute` | `(opts?: AsyncDataExecuteOptions) => Promise<void>` | Alias for `refresh`. |
230
231
  | `error` | `Ref<ErrorT \| undefined>` | Error object if the data fetching failed. |
231
232
  | `status` | `Ref<'idle' \| 'pending' \| 'success' \| 'error'>` | Status of the data request. See below for possible values. |
233
+ | `pending` | `Ref<boolean>` | Boolean flag indicating whether the current request is in progress. |
232
234
  | `clear` | `() => void` | Resets `data` to `undefined` (or the value of `options.default()` if provided), `error` to `undefined`, set `status` to `idle`, and cancels any pending requests. |
233
235
 
234
236
  ### Status values
@@ -76,6 +76,7 @@ Returns the same `AsyncData` object as [`useFetch`](/docs/4.x/api/composables/us
76
76
  | `execute` | `(opts?: AsyncDataExecuteOptions) => Promise<void>` | Alias for `refresh`. |
77
77
  | `error` | `Ref<ErrorT \| undefined>` | Error object if the data fetching failed. |
78
78
  | `status` | `Ref<'idle' \| 'pending' \| 'success' \| 'error'>` | Status of the data request. |
79
+ | `pending` | `Ref<boolean>` | Boolean flag indicating whether the current request is in progress. |
79
80
  | `clear` | `() => void` | Resets `data` to `undefined`, `error` to `undefined`, sets `status` to `idle`, and cancels any pending requests. |
80
81
 
81
82
  :read-more{to="/docs/4.x/api/composables/use-fetch#return-values"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/docs-nightly",
3
- "version": "4.4.0-29550724.be97f20e",
3
+ "version": "4.4.0-29551604.0a8a57da",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",