@nuxt/docs 3.21.0 → 3.21.2
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.
- package/1.getting-started/02.installation.md +2 -1
- package/1.getting-started/06.styling.md +1 -1
- package/1.getting-started/15.prerendering.md +8 -0
- package/1.getting-started/16.deployment.md +2 -3
- package/1.getting-started/17.testing.md +63 -8
- package/1.getting-started/18.upgrade.md +5 -2
- package/2.directory-structure/1.layouts.md +1 -1
- package/2.directory-structure/1.modules.md +4 -0
- package/2.directory-structure/1.server.md +7 -7
- package/3.guide/0.index.md +0 -3
- package/3.guide/1.concepts/1.rendering.md +4 -0
- package/3.guide/2.best-practices/hydration.md +11 -11
- package/3.guide/2.best-practices/performance.md +2 -3
- package/3.guide/3.ai/1.mcp.md +1 -1
- package/3.guide/3.ai/2.llms-txt.md +1 -1
- package/3.guide/4.modules/3.recipes-basics.md +98 -0
- package/3.guide/5.recipes/4.sessions-and-authentication.md +2 -2
- package/3.guide/6.going-further/1.experimental-features.md +5 -1
- package/3.guide/6.going-further/2.hooks.md +1 -1
- package/4.api/1.components/8.nuxt-island.md +1 -1
- package/4.api/2.composables/use-async-data.md +1 -1
- package/4.api/2.composables/use-fetch.md +2 -0
- package/4.api/2.composables/use-lazy-fetch.md +1 -0
- package/4.api/2.composables/use-route-announcer.md +1 -1
- package/4.api/4.commands/add.md +1 -1
- package/4.api/4.commands/build.md +1 -1
- package/4.api/5.kit/11.nitro.md +6 -2
- package/4.api/5.kit/4.autoimports.md +5 -1
- package/5.community/2.getting-help.md +1 -1
- package/5.community/6.roadmap.md +4 -4
- package/7.migration/11.server.md +1 -1
- package/package.json +1 -1
|
@@ -20,13 +20,14 @@ Or follow the steps below to set up a new Nuxt project on your computer.
|
|
|
20
20
|
### Prerequisites
|
|
21
21
|
|
|
22
22
|
- **Node.js** - [`20.x`](https://nodejs.org/en) or newer (but we recommend the [active LTS release](https://github.com/nodejs/release#release-schedule))
|
|
23
|
-
- **Text editor** - There is no IDE requirement, but we recommend [Visual Studio Code](https://code.visualstudio.com/) with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously known as Volar) or [WebStorm](https://www.jetbrains.com/webstorm/), which, along with [other JetBrains IDEs](https://www.jetbrains.com/ides/), offers great Nuxt support right out-of-the-box.
|
|
23
|
+
- **Text editor** - There is no IDE requirement, but we recommend [Visual Studio Code](https://code.visualstudio.com/) with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously known as Volar) or [WebStorm](https://www.jetbrains.com/webstorm/), which, along with [other JetBrains IDEs](https://www.jetbrains.com/ides/), offers great Nuxt support right out-of-the-box. If you use another editor, such as Neovim, you can configure [Vue Language Server](https://github.com/vuejs/language-tools) support by following the [Vue Language Tools setup guides](https://github.com/vuejs/language-tools/wiki).
|
|
24
24
|
- **Terminal** - In order to run Nuxt commands
|
|
25
25
|
|
|
26
26
|
::note
|
|
27
27
|
::details
|
|
28
28
|
:summary[Additional notes for an optimal setup:]
|
|
29
29
|
- **Node.js**: Make sure to use an even numbered version (20, 22, etc.)
|
|
30
|
+
- **Neovim**: When configuring the Vue TypeScript plugin, make sure `location` points to the `@vue/language-server` package directory, not its binary. See the [Neovim setup guide](https://github.com/vuejs/language-tools/wiki/Neovim) for a working configuration.
|
|
30
31
|
- **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.
|
|
31
32
|
- **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.
|
|
32
33
|
::
|
|
@@ -155,7 +155,7 @@ Nuxt uses `unhead` under the hood, and you can refer to [its full documentation]
|
|
|
155
155
|
|
|
156
156
|
If you need more advanced control, you can intercept the rendered html with a hook and modify the head programmatically.
|
|
157
157
|
|
|
158
|
-
Create a plugin in
|
|
158
|
+
Create a plugin in `~~/server/plugins/my-plugin.ts` like this:
|
|
159
159
|
|
|
160
160
|
<!-- TODO: figure out how to use twoslash to inject types for a different context -->
|
|
161
161
|
|
|
@@ -49,6 +49,14 @@ Working of the Nitro crawler:
|
|
|
49
49
|
|
|
50
50
|
This is important to understand since pages that are not linked to a discoverable page can't be pre-rendered automatically.
|
|
51
51
|
|
|
52
|
+
### Payload Extraction
|
|
53
|
+
|
|
54
|
+
Nuxt generates `_payload.json` alongside HTML for:
|
|
55
|
+
- Prerendered routes (at build time)
|
|
56
|
+
- ISR/SWR routes (on first request)
|
|
57
|
+
|
|
58
|
+
Payloads contain serialized data from `useAsyncData` and `useFetch`. Client-side navigation loads these cached payloads instead of re-fetching data. Configure dynamic routes like `pages/[...slug].vue` with route rules: `'/**': { isr: true }`.
|
|
59
|
+
|
|
52
60
|
::read-more{to="/docs/3.x/api/commands/generate#nuxt-generate"}
|
|
53
61
|
Read more about the `nuxt generate` command.
|
|
54
62
|
::
|
|
@@ -120,9 +120,8 @@ In most cases, Nuxt can work with third-party content that is not generated or c
|
|
|
120
120
|
|
|
121
121
|
Accordingly, you should make sure that the following options are unchecked / disabled in Cloudflare. Otherwise, unnecessary re-rendering or hydration errors could impact your production application.
|
|
122
122
|
|
|
123
|
-
1. Speed >
|
|
124
|
-
2.
|
|
125
|
-
3. Scrape Shield > Disable "Email Address Obfuscation"
|
|
123
|
+
1. Speed > Settings > Content Optimization > Disable "Rocket Loader™"
|
|
124
|
+
2. Security > Settings > Disable "Email Address Obfuscation"
|
|
126
125
|
|
|
127
126
|
With these settings, you can be sure that Cloudflare won't inject scripts into your Nuxt application that may cause unwanted side effects.
|
|
128
127
|
|
|
@@ -108,6 +108,7 @@ If you prefer a simpler setup and want all tests to run in the Nuxt environment,
|
|
|
108
108
|
|
|
109
109
|
```ts twoslash
|
|
110
110
|
import { defineVitestConfig } from '@nuxt/test-utils/config'
|
|
111
|
+
import { fileURLToPath } from 'node:url'
|
|
111
112
|
|
|
112
113
|
export default defineVitestConfig({
|
|
113
114
|
test: {
|
|
@@ -268,6 +269,10 @@ it('can also mount an app', async () => {
|
|
|
268
269
|
})
|
|
269
270
|
```
|
|
270
271
|
|
|
272
|
+
The options object accepts `@vue/test-utils` mount options and the following properties:
|
|
273
|
+
|
|
274
|
+
- `route`: the initial route, or `false` to skip the initial route change (default `/`).
|
|
275
|
+
|
|
271
276
|
#### `renderSuspended`
|
|
272
277
|
|
|
273
278
|
`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.
|
|
@@ -320,14 +325,18 @@ it('can also render an app', async () => {
|
|
|
320
325
|
})
|
|
321
326
|
```
|
|
322
327
|
|
|
328
|
+
The options object accepts `@testing-library/vue` render options and the following properties:
|
|
329
|
+
|
|
330
|
+
- `route`: the initial route, or `false` to skip the initial route change (default `/`).
|
|
331
|
+
|
|
323
332
|
#### `mockNuxtImport`
|
|
324
333
|
|
|
325
|
-
`mockNuxtImport` allows you to mock Nuxt's auto import functionality. For example, to mock `
|
|
334
|
+
`mockNuxtImport` allows you to mock Nuxt's auto import functionality. For example, to mock `useState`, you can do so like this:
|
|
326
335
|
|
|
327
336
|
```ts twoslash
|
|
328
337
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
329
338
|
|
|
330
|
-
mockNuxtImport('
|
|
339
|
+
mockNuxtImport('useState', () => {
|
|
331
340
|
return () => {
|
|
332
341
|
return { value: 'mocked storage' }
|
|
333
342
|
}
|
|
@@ -336,6 +345,27 @@ mockNuxtImport('useStorage', () => {
|
|
|
336
345
|
// your tests here
|
|
337
346
|
```
|
|
338
347
|
|
|
348
|
+
You can explicitly type the mock for type safety, and use the original implementation passed to the factory function when mocking complex functionality.
|
|
349
|
+
|
|
350
|
+
```ts twoslash [test/nuxt/import.test.ts]
|
|
351
|
+
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
352
|
+
|
|
353
|
+
mockNuxtImport<typeof useState>('useState', (original) => {
|
|
354
|
+
return (...args) => {
|
|
355
|
+
return { ...original('some-key'), value: 'mocked state' }
|
|
356
|
+
}
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
// or specify the target to mock
|
|
360
|
+
mockNuxtImport(useState, (original) => {
|
|
361
|
+
return (...args) => {
|
|
362
|
+
return { ...original('some-key'), value: 'mocked state' }
|
|
363
|
+
}
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
// your tests here
|
|
367
|
+
```
|
|
368
|
+
|
|
339
369
|
::note
|
|
340
370
|
`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).
|
|
341
371
|
::
|
|
@@ -346,24 +376,43 @@ If you need to mock a Nuxt import and provide different implementations between
|
|
|
346
376
|
import { vi } from 'vitest'
|
|
347
377
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
348
378
|
|
|
349
|
-
const {
|
|
379
|
+
const { useStateMock } = vi.hoisted(() => {
|
|
350
380
|
return {
|
|
351
|
-
|
|
381
|
+
useStateMock: vi.fn(() => {
|
|
352
382
|
return { value: 'mocked storage' }
|
|
353
383
|
}),
|
|
354
384
|
}
|
|
355
385
|
})
|
|
356
386
|
|
|
357
|
-
mockNuxtImport('
|
|
358
|
-
return
|
|
387
|
+
mockNuxtImport('useState', () => {
|
|
388
|
+
return useStateMock
|
|
359
389
|
})
|
|
360
390
|
|
|
361
391
|
// Then, inside a test
|
|
362
|
-
|
|
392
|
+
useStateMock.mockImplementation(() => {
|
|
363
393
|
return { value: 'something else' }
|
|
364
394
|
})
|
|
365
395
|
```
|
|
366
396
|
|
|
397
|
+
If you need to mock behavior only inside a test, you can also use the following approach.
|
|
398
|
+
|
|
399
|
+
```ts twoslash
|
|
400
|
+
import { beforeEach, vi } from 'vitest'
|
|
401
|
+
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
402
|
+
|
|
403
|
+
mockNuxtImport(useRoute, original => vi.fn(original))
|
|
404
|
+
|
|
405
|
+
beforeEach(() => {
|
|
406
|
+
vi.resetAllMocks()
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
// Then, inside a test
|
|
410
|
+
const useRouteOriginal = vi.mocked(useRoute).getMockImplementation()!
|
|
411
|
+
vi.mocked(useRoute).mockImplementation(
|
|
412
|
+
(...args) => ({ ...useRouteOriginal(...args), path: '/mocked' }),
|
|
413
|
+
)
|
|
414
|
+
```
|
|
415
|
+
|
|
367
416
|
#### `mockComponent`
|
|
368
417
|
|
|
369
418
|
`mockComponent` allows you to mock Nuxt's component.
|
|
@@ -445,6 +494,12 @@ registerEndpoint('/test/', {
|
|
|
445
494
|
})
|
|
446
495
|
```
|
|
447
496
|
|
|
497
|
+
This object accepts the following properties:
|
|
498
|
+
|
|
499
|
+
- `handler`: the event handler function
|
|
500
|
+
- `method`: (optional) HTTP method to match (e.g., 'GET', 'POST')
|
|
501
|
+
- `once`: (optional) if true, the handler will only be used for the first matching request and then automatically removed
|
|
502
|
+
|
|
448
503
|
> **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/3.x/getting-started/configuration#environment-overrides) (`$test`) so all your requests will go to Nitro server.
|
|
449
504
|
|
|
450
505
|
#### Conflict with End-To-End Testing
|
|
@@ -458,7 +513,7 @@ If you would like to use both the end-to-end and unit testing functionality of `
|
|
|
458
513
|
```ts twoslash
|
|
459
514
|
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
|
|
460
515
|
|
|
461
|
-
mockNuxtImport('
|
|
516
|
+
mockNuxtImport('useState', () => {
|
|
462
517
|
return () => {
|
|
463
518
|
return { value: 'mocked storage' }
|
|
464
519
|
}
|
|
@@ -192,6 +192,7 @@ Nuxt now defaults to a new directory structure, with backwards compatibility (so
|
|
|
192
192
|
- `layers/`, `modules/` and `public/` are resolved relative to `<rootDir>` by default
|
|
193
193
|
- if using [Nuxt Content v2.13+](https://github.com/nuxt/content/pull/2649), `content/` is resolved relative to `<rootDir>`
|
|
194
194
|
- a new `dir.app` is added, which is the directory we look for `router.options.ts` and `spa-loading-template.html` - this defaults to `<srcDir>/`
|
|
195
|
+
- a new [`shared/`](/docs/3.x/directory-structure/shared) directory is available for code shared between the Vue app and the Nitro server, with auto-imports for `shared/utils/` and `shared/types/`
|
|
195
196
|
|
|
196
197
|
<details>
|
|
197
198
|
|
|
@@ -218,6 +219,8 @@ modules/
|
|
|
218
219
|
node_modules/
|
|
219
220
|
public/
|
|
220
221
|
shared/
|
|
222
|
+
types/
|
|
223
|
+
utils/
|
|
221
224
|
server/
|
|
222
225
|
api/
|
|
223
226
|
middleware/
|
|
@@ -246,14 +249,14 @@ With this new structure, the `~` alias now points to the `app/` directory by def
|
|
|
246
249
|
|
|
247
250
|
1. Create a new directory called `app/`.
|
|
248
251
|
1. Move your `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` and `utils/` folders under it, as well as `app.vue`, `error.vue`, `app.config.ts`. If you have an `app/router-options.ts` or `app/spa-loading-template.html`, these paths remain the same.
|
|
249
|
-
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
|
|
252
|
+
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/`, `shared/` and `server/` folders remain outside the `app/` folder, in the root of your project.
|
|
250
253
|
1. Remember to update any third-party configuration files to work with the new directory structure, such as your `tailwindcss` or `eslint` configuration (if required - `@nuxtjs/tailwindcss` should automatically configure `tailwindcss` correctly).
|
|
251
254
|
|
|
252
255
|
::tip
|
|
253
256
|
You can automate this migration by running `npx codemod@latest nuxt/4/file-structure`
|
|
254
257
|
::
|
|
255
258
|
|
|
256
|
-
However, migration is _not required_. If you wish to keep your current folder structure, Nuxt should auto-detect it. (If it does not, please raise an issue.) The one exception is that if you _already_ have a custom `srcDir`. In this case, you should be aware that your `modules/`, `public/` and `server/` folders will be resolved from your `rootDir` rather than from your custom `srcDir`. You can override this by configuring `dir.modules`, `dir.public` and `serverDir` if you need to.
|
|
259
|
+
However, migration is _not required_. If you wish to keep your current folder structure, Nuxt should auto-detect it. (If it does not, please raise an issue.) The one exception is that if you _already_ have a custom `srcDir`. In this case, you should be aware that your `modules/`, `public/`, `shared/` and `server/` folders will be resolved from your `rootDir` rather than from your custom `srcDir`. You can override this by configuring `dir.modules`, `dir.public` and `serverDir` if you need to.
|
|
257
260
|
|
|
258
261
|
You can also force a v3 folder structure with the following configuration:
|
|
259
262
|
|
|
@@ -122,7 +122,7 @@ File | Layout Name
|
|
|
122
122
|
|
|
123
123
|
You can also use the [`setPageLayout`](/docs/3.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 {
|
|
@@ -52,6 +52,10 @@ export default defineEventHandler(() => {
|
|
|
52
52
|
|
|
53
53
|
When starting Nuxt, the `hello` module will be registered and the `/api/hello` route will be available.
|
|
54
54
|
|
|
55
|
+
::note
|
|
56
|
+
Note that all components, pages, composables and other files that would be normally placed in your `app/` directory need to be in `modules/your-module/runtime/app/`. This ensures they can be type-checked properly.
|
|
57
|
+
::
|
|
58
|
+
|
|
55
59
|
Modules are executed in the following sequence:
|
|
56
60
|
- First, the modules defined in [`nuxt.config.ts`](/docs/3.x/api/nuxt-config#modules-1) are loaded.
|
|
57
61
|
- Then, modules found in the `modules/` directory are executed, and they load in alphabetical order.
|
|
@@ -43,11 +43,11 @@ const { data } = await useFetch('/api/hello')
|
|
|
43
43
|
|
|
44
44
|
## Server Routes
|
|
45
45
|
|
|
46
|
-
Files inside the
|
|
46
|
+
Files inside the `~~/server/api` are automatically prefixed with `/api` in their route.
|
|
47
47
|
|
|
48
48
|
:video-accordion{title="Watch a video from Vue School on API routes" videoId="761468863" platform="vimeo"}
|
|
49
49
|
|
|
50
|
-
To add server routes without `/api` prefix, put them into
|
|
50
|
+
To add server routes without `/api` prefix, put them into `~~/server/routes` directory.
|
|
51
51
|
|
|
52
52
|
**Example:**
|
|
53
53
|
|
|
@@ -63,7 +63,7 @@ Note that currently server routes do not support the full functionality of dynam
|
|
|
63
63
|
|
|
64
64
|
## Server Middleware
|
|
65
65
|
|
|
66
|
-
Nuxt will automatically read in any file in the
|
|
66
|
+
Nuxt will automatically read in any file in the `~~/server/middleware` to create server middleware for your project.
|
|
67
67
|
|
|
68
68
|
Middleware handlers will run on every request before any other server route to add or check headers, log requests, or extend the event's request object.
|
|
69
69
|
|
|
@@ -87,7 +87,7 @@ export default defineEventHandler((event) => {
|
|
|
87
87
|
|
|
88
88
|
## Server Plugins
|
|
89
89
|
|
|
90
|
-
Nuxt will automatically read any files in the
|
|
90
|
+
Nuxt will automatically read any files in the `~~/server/plugins` directory and register them as Nitro plugins. This allows extending Nitro's runtime behavior and hooking into lifecycle events.
|
|
91
91
|
|
|
92
92
|
**Example:**
|
|
93
93
|
|
|
@@ -105,7 +105,7 @@ Server routes are powered by [h3js/h3](https://github.com/h3js/h3) which comes w
|
|
|
105
105
|
|
|
106
106
|
:read-more{to="https://www.jsdocs.io/package/h3#package-index-functions" title="Available H3 Request Helpers" target="_blank"}
|
|
107
107
|
|
|
108
|
-
You can add more helpers yourself inside the
|
|
108
|
+
You can add more helpers yourself inside the `~~/server/utils` directory.
|
|
109
109
|
|
|
110
110
|
For example, you can define a custom handler utility that wraps the original handler and performs additional operations before returning the final response.
|
|
111
111
|
|
|
@@ -228,7 +228,7 @@ export default defineEventHandler((event) => {
|
|
|
228
228
|
|
|
229
229
|
Catch-all routes are helpful for fallback route handling.
|
|
230
230
|
|
|
231
|
-
For example, creating a file named
|
|
231
|
+
For example, creating a file named `~~/server/api/foo/[...].ts` will register a catch-all route for all requests that do not match any route handler, such as `/api/foo/bar/baz`.
|
|
232
232
|
|
|
233
233
|
```ts [server/api/foo/[...\\].ts]
|
|
234
234
|
export default defineEventHandler((event) => {
|
|
@@ -238,7 +238,7 @@ export default defineEventHandler((event) => {
|
|
|
238
238
|
})
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
You can set a name for the catch-all route by using
|
|
241
|
+
You can set a name for the catch-all route by using `~~/server/api/foo/[...slug].ts` and access it via `event.context.params.slug`.
|
|
242
242
|
|
|
243
243
|
```ts [server/api/foo/[...slug\\].ts]
|
|
244
244
|
export default defineEventHandler((event) => {
|
package/3.guide/0.index.md
CHANGED
|
@@ -13,9 +13,6 @@ surround: false
|
|
|
13
13
|
::card{icon="i-lucide-square-check" title="Best Practices" to="/docs/3.x/guide/best-practices"}
|
|
14
14
|
Learn about best practices when developing with Nuxt.
|
|
15
15
|
::
|
|
16
|
-
::card{icon="i-lucide-bot" title="Working with AI" to="/docs/4.x/guide/ai"}
|
|
17
|
-
Integrate AI tools into your Nuxt workflow with MCP Server and LLMs.txt.
|
|
18
|
-
::
|
|
19
16
|
::card{icon="i-lucide-box" title="Module Author Guide" to="/docs/3.x/guide/modules"}
|
|
20
17
|
Learn how to create Nuxt modules to integrate, enhance or extend any Nuxt application.
|
|
21
18
|
::
|
|
@@ -193,6 +193,10 @@ The different properties you can use are the following:
|
|
|
193
193
|
- `noScripts: boolean`{lang=ts} - Disables rendering of Nuxt scripts and JS resource hints for sections of your site.
|
|
194
194
|
- `appMiddleware: string | string[] | Record<string, boolean>`{lang=ts} - Allows you to define middleware that should or should not run for page paths within the Vue app part of your application (that is, not your Nitro routes)
|
|
195
195
|
|
|
196
|
+
::note
|
|
197
|
+
Routes using `isr` or `swr` also generate `_payload.json` files alongside HTML. Client-side navigation loads these cached payloads instead of re-fetching data. Configure dynamic routes like `pages/[...slug].vue` with glob patterns: `'/**': { isr: true }`.
|
|
198
|
+
::
|
|
199
|
+
|
|
196
200
|
Whenever possible, route rules will be automatically applied to the deployment platform's native rules for optimal performances (Netlify and Vercel are currently supported).
|
|
197
201
|
|
|
198
202
|
::important
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
+
## How to detect them
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
### Development Console Warnings
|
|
27
27
|
|
|
28
28
|
Vue will log hydration mismatch warnings in the browser console during development:
|
|
29
29
|
|
|
30
30
|

|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
## Common reasons
|
|
33
33
|
|
|
34
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
132
|
+
### Dynamic Content Based on Time
|
|
133
133
|
|
|
134
134
|
**Problem**: Content that changes based on current time.
|
|
135
135
|
|
|
@@ -142,9 +142,8 @@ Images in your website can usually be separated by importance; the ones that are
|
|
|
142
142
|
<NuxtImg
|
|
143
143
|
src="/hero-banner.jpg"
|
|
144
144
|
format="webp"
|
|
145
|
-
preload
|
|
145
|
+
:preload="{ fetchPriority: 'high' }"
|
|
146
146
|
loading="eager"
|
|
147
|
-
fetch-priority="high"
|
|
148
147
|
width="200"
|
|
149
148
|
height="100"
|
|
150
149
|
/>
|
|
@@ -154,7 +153,7 @@ Images in your website can usually be separated by importance; the ones that are
|
|
|
154
153
|
src="/facebook-logo.jpg"
|
|
155
154
|
format="webp"
|
|
156
155
|
loading="lazy"
|
|
157
|
-
|
|
156
|
+
fetchpriority="low"
|
|
158
157
|
width="200"
|
|
159
158
|
height="100"
|
|
160
159
|
/>
|
package/3.guide/3.ai/1.mcp.md
CHANGED
|
@@ -79,7 +79,7 @@ The Nuxt connector will appear in the composer's "Developer mode" tool later dur
|
|
|
79
79
|
### Claude Code
|
|
80
80
|
|
|
81
81
|
::note{icon="i-lucide-info"}
|
|
82
|
-
**Ensure Claude Code is installed** - Visit [Anthropic's documentation](https://
|
|
82
|
+
**Ensure Claude Code is installed** - Visit [Anthropic's documentation](https://code.claude.com/docs/en/quickstart) for installation instructions.
|
|
83
83
|
::
|
|
84
84
|
|
|
85
85
|
Add the server using the CLI command:
|
|
@@ -42,7 +42,7 @@ Nuxt provides specialized LLMs.txt files that you can reference in Cursor for be
|
|
|
42
42
|
1. **Direct reference**: Mention the LLMs.txt URLs when asking questions
|
|
43
43
|
2. Add these specific URLs to your project context using `@docs`
|
|
44
44
|
|
|
45
|
-
[Read more about Cursor Web and Docs Search](https://cursor.com/docs/context/
|
|
45
|
+
[Read more about Cursor Web and Docs Search](https://cursor.com/docs/context/mentions)
|
|
46
46
|
|
|
47
47
|
### Windsurf
|
|
48
48
|
|
|
@@ -139,6 +139,10 @@ It is highly recommended to prefix your exports to avoid conflicts with user cod
|
|
|
139
139
|
Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.
|
|
140
140
|
::
|
|
141
141
|
|
|
142
|
+
::note
|
|
143
|
+
Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.
|
|
144
|
+
::
|
|
145
|
+
|
|
142
146
|
## Add Composables
|
|
143
147
|
|
|
144
148
|
If your module should provide composables, you can use the `addImports` utility to add them as auto-imports for Nuxt to resolve.
|
|
@@ -200,6 +204,100 @@ It is highly recommended to prefix your exports to avoid conflicts with user cod
|
|
|
200
204
|
Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.
|
|
201
205
|
::
|
|
202
206
|
|
|
207
|
+
### Add Keyed Functions
|
|
208
|
+
|
|
209
|
+
Sometimes, you may need to maintain state consistency between the server and the client. Examples include Nuxt's built-in `useState` or `useAsyncData` composables. Nuxt provides a way to register such functions for automatic key injection.
|
|
210
|
+
|
|
211
|
+
When a function is registered, Nuxt’s compiler automatically injects a unique key as an additional argument if the function is called with fewer than the specified number of arguments. This key remains stable between server-side rendering and client hydration.
|
|
212
|
+
|
|
213
|
+
::tip
|
|
214
|
+
The injected key is a hash derived from the file path and call location.
|
|
215
|
+
::
|
|
216
|
+
|
|
217
|
+
Use the `keyedComposables` option to register your function:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
|
221
|
+
|
|
222
|
+
export default defineNuxtModule({
|
|
223
|
+
setup (options, nuxt) {
|
|
224
|
+
const resolver = createResolver(import.meta.url)
|
|
225
|
+
|
|
226
|
+
nuxt.options.optimization.keyedComposables.push({
|
|
227
|
+
name: 'useMyState',
|
|
228
|
+
source: resolver.resolve('./runtime/composables/state'),
|
|
229
|
+
argumentLength: 2,
|
|
230
|
+
})
|
|
231
|
+
},
|
|
232
|
+
})
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The `keyedComposables` configuration accepts an array of objects with the following properties:
|
|
236
|
+
|
|
237
|
+
| Property | Type | Description |
|
|
238
|
+
|------------------|----------|----------------------------------------------------------------------------------------------------------------------------|
|
|
239
|
+
| `name` | `string` | The function name. Use `'default'` for default exports (the callable name will be derived from the filename in camelCase). |
|
|
240
|
+
| `source` | `string` | Resolved path to the file where the function is defined. Supports Nuxt aliases (`~`, `@`, etc.) |
|
|
241
|
+
| `argumentLength` | `number` | Maximum number of arguments the function accepts. When called with fewer arguments, a unique key is injected. |
|
|
242
|
+
|
|
243
|
+
For example, with `argumentLength: 2`:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
useMyState() // useMyState('$HJiaryoL2y')
|
|
247
|
+
useMyState('myKey') // useMyState('myKey', '$HJiaryoL2y')
|
|
248
|
+
useMyState('a', 'b') // not transformed (already has 2 arguments)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
::warning
|
|
252
|
+
The key injection plugin verifies the exact resolved import source of each function call. It does not follow barrel exports. The function must be exported from the exact source file specified in the `source` property.
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
// ✅ Works - direct import matches the configured source
|
|
256
|
+
import { useMyState } from 'my-module/runtime/composables/state'
|
|
257
|
+
|
|
258
|
+
// ❌ Won't work - re-exported through a barrel file
|
|
259
|
+
import { useMyState } from 'my-module/runtime/composables' // index.ts barrel
|
|
260
|
+
```
|
|
261
|
+
::
|
|
262
|
+
|
|
263
|
+
::warning
|
|
264
|
+
The function call must be statically analyzable. The compiler cannot inject keys for dynamic or indirect function calls.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { useMyState } from 'my-module/runtime/composables/state'
|
|
268
|
+
import * as composables from 'my-module/runtime/composables/state'
|
|
269
|
+
|
|
270
|
+
// ✅ Works - direct function call
|
|
271
|
+
useMyState()
|
|
272
|
+
|
|
273
|
+
// ✅ Works - called on namespace import
|
|
274
|
+
composables.useMyState()
|
|
275
|
+
|
|
276
|
+
// ❌ Won't work - dynamic property access
|
|
277
|
+
const name = 'useMyState'
|
|
278
|
+
composables[name]()
|
|
279
|
+
|
|
280
|
+
// ❌ Won't work - reassigned to a variable
|
|
281
|
+
const myFn = useMyState
|
|
282
|
+
myFn()
|
|
283
|
+
|
|
284
|
+
// ❌ Won't work - passed as a callback
|
|
285
|
+
someFunction(useMyState)
|
|
286
|
+
|
|
287
|
+
// ❌ Won't work - destructured with renaming in a nested scope
|
|
288
|
+
function setup () {
|
|
289
|
+
const { useMyState: localState } = composables
|
|
290
|
+
localState() // not transformed
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ...
|
|
294
|
+
```
|
|
295
|
+
::
|
|
296
|
+
|
|
297
|
+
::note
|
|
298
|
+
Note that all components, pages, composables and other files that would be normally placed in your `app/` folder need to be in `runtime/app/`. This will mean they can be type checked properly.
|
|
299
|
+
::
|
|
300
|
+
|
|
203
301
|
## Add Server Routes
|
|
204
302
|
|
|
205
303
|
```ts
|
|
@@ -47,7 +47,7 @@ Let's create a `/api/login` API route that will accept a POST request with the e
|
|
|
47
47
|
import { z } from 'zod'
|
|
48
48
|
|
|
49
49
|
const bodySchema = z.object({
|
|
50
|
-
email: z.
|
|
50
|
+
email: z.email(),
|
|
51
51
|
password: z.string().min(8),
|
|
52
52
|
})
|
|
53
53
|
|
|
@@ -210,7 +210,7 @@ We've successfully set up a very basic user authentication and session managemen
|
|
|
210
210
|
|
|
211
211
|
As next steps, you can:
|
|
212
212
|
- Add authentication using the [20+ supported OAuth providers](https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#supported-oauth-providers)
|
|
213
|
-
- Add a database to store users, see [Nitro SQL Database](https://nitro.build/guide/database) or [NuxtHub SQL Database](https://hub.nuxt.com/docs/
|
|
213
|
+
- Add a database to store users, see [Nitro SQL Database](https://nitro.build/guide/database) or [NuxtHub SQL Database](https://hub.nuxt.com/docs/database)
|
|
214
214
|
- Let user signup with email & password using [password hashing](https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#password-hashing)
|
|
215
215
|
- Add support for [WebAuthn / Passkeys](https://github.com/atinux/nuxt-auth-utils?tab=readme-ov-file#webauthn-passkey)
|
|
216
216
|
|
|
@@ -370,7 +370,11 @@ Out of the box, this will enable typed usage of [`navigateTo`](/docs/3.x/api/uti
|
|
|
370
370
|
You can even get typed params within a page by using `const route = useRoute('route-name')`.
|
|
371
371
|
|
|
372
372
|
::important
|
|
373
|
-
If you use `pnpm` without `shamefully-hoist=true`, you will need to
|
|
373
|
+
If you use `pnpm` without `shamefully-hoist=true`, you will need to add `unplugin-vue-router` as a hoist pattern in your `pnpm-workspace.yaml` in order for this feature to work.
|
|
374
|
+
```yaml
|
|
375
|
+
publicHoistPattern:
|
|
376
|
+
- "unplugin-vue-router"
|
|
377
|
+
```
|
|
374
378
|
::
|
|
375
379
|
|
|
376
380
|
:video-accordion{title="Watch a video from Daniel Roe explaining type-safe routing in Nuxt" videoId="SXk-L19gTZk"}
|
|
@@ -57,7 +57,7 @@ Explore all available App hooks.
|
|
|
57
57
|
|
|
58
58
|
These hooks are available for [server plugins](/docs/3.x/directory-structure/server#server-plugins) to hook into Nitro's runtime behavior.
|
|
59
59
|
|
|
60
|
-
```ts [
|
|
60
|
+
```ts [~~/server/plugins/test.ts]
|
|
61
61
|
export default defineNitroPlugin((nitroApp) => {
|
|
62
62
|
nitroApp.hooks.hook('render:html', (html, { event }) => {
|
|
63
63
|
console.log('render:html', html)
|
|
@@ -74,4 +74,4 @@ Some slots are reserved to `NuxtIsland` for special cases.
|
|
|
74
74
|
- **parameters**:
|
|
75
75
|
- **error**:
|
|
76
76
|
- **type**: `unknown`
|
|
77
|
-
- **description**: emitted when
|
|
77
|
+
- **description**: emitted when `NuxtIsland` fails to fetch the new island.
|
|
@@ -148,7 +148,7 @@ The `handler` function should be **side-effect free** to ensure predictable beha
|
|
|
148
148
|
- `immediate`: when set to `false`, will prevent the request from firing immediately. (defaults to `true`)
|
|
149
149
|
- `default`: a factory function to set the default value of the `data`, before the async function resolves - useful with the `lazy: true` or `immediate: false` option
|
|
150
150
|
- `transform`: a function that can be used to alter `handler` function result after resolving
|
|
151
|
-
- `getCachedData`: Provide a function which returns cached data.
|
|
151
|
+
- `getCachedData`: Provide a function which returns cached data. An `undefined` return value will trigger a fetch. By default, this is:
|
|
152
152
|
```ts
|
|
153
153
|
const getDefaultCachedData = (key, nuxtApp, ctx) => nuxtApp.isHydrating
|
|
154
154
|
? nuxtApp.payload.data[key]
|
|
@@ -161,6 +161,7 @@ type AsyncDataRequestContext = {
|
|
|
161
161
|
|
|
162
162
|
type AsyncData<DataT, ErrorT> = {
|
|
163
163
|
data: Ref<DataT | null>
|
|
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/3.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/3.x/api/composables/use-fetch#return-values"}
|
|
@@ -15,7 +15,7 @@ This composable is available in Nuxt v3.12+.
|
|
|
15
15
|
## Description
|
|
16
16
|
|
|
17
17
|
A composable which observes the page title changes and updates the announcer message accordingly. Used by [`<NuxtRouteAnnouncer>`](/docs/3.x/api/components/nuxt-route-announcer) and controllable.
|
|
18
|
-
It hooks into Unhead's
|
|
18
|
+
It hooks into Unhead's `dom:rendered` hook to read the page's title and set it as the announcer message.
|
|
19
19
|
|
|
20
20
|
## Parameters
|
|
21
21
|
|
package/4.api/4.commands/add.md
CHANGED
|
@@ -4,7 +4,7 @@ description: "Scaffold an entity into your Nuxt application."
|
|
|
4
4
|
links:
|
|
5
5
|
- label: Source
|
|
6
6
|
icon: i-simple-icons-github
|
|
7
|
-
to: https://github.com/nuxt/cli/blob/main/packages/nuxi/src/commands/add.ts
|
|
7
|
+
to: https://github.com/nuxt/cli/blob/main/packages/nuxi/src/commands/add-template.ts
|
|
8
8
|
size: xs
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -32,7 +32,7 @@ The `build` command creates a `.output` directory with all your application, ser
|
|
|
32
32
|
| `--cwd=<directory>` | | Specify the working directory, this takes precedence over ROOTDIR (default: `.`) |
|
|
33
33
|
| `--logLevel=<silent\|info\|verbose>` | | Specify build-time log level |
|
|
34
34
|
| `--prerender` | | Build Nuxt and prerender static routes |
|
|
35
|
-
| `--preset
|
|
35
|
+
| `--preset=<preset>` | | Specify Nitro server preset. Available presets depend on Nitro (e.g. `node-server`, `vercel`, `netlify`, `static`) |
|
|
36
36
|
| `--dotenv` | | Path to `.env` file to load, relative to the root directory |
|
|
37
37
|
| `--envName` | | The environment to use when resolving configuration overrides (default is `production` when building, and `development` when running the dev server) |
|
|
38
38
|
| `-e, --extends=<layer-name>` | | Extend from a Nuxt layer |
|
package/4.api/5.kit/11.nitro.md
CHANGED
|
@@ -301,6 +301,10 @@ function addPrerenderRoutes (routes: string | string[]): void
|
|
|
301
301
|
|
|
302
302
|
Add imports to the server. It makes your imports available in Nitro without the need to import them manually.
|
|
303
303
|
|
|
304
|
+
::warning
|
|
305
|
+
If you want to provide a utility that works in both server and client contexts and is usable in the [`shared/`](/docs/3.x/directory-structure/shared) directory, the function must be imported from the same source file for both [`addImports`](/docs/3.x/api/kit/autoimports#addimports) and `addServerImports` and should have identical signature. That source file should not import anything context-specific (i.e., Nitro context, Nuxt app context) or else it might cause errors during type-checking.
|
|
306
|
+
::
|
|
307
|
+
|
|
304
308
|
### Usage
|
|
305
309
|
|
|
306
310
|
```ts twoslash
|
|
@@ -422,10 +426,10 @@ export default defineEventHandler(() => {
|
|
|
422
426
|
## `addServerScanDir`
|
|
423
427
|
|
|
424
428
|
Add directories to be scanned by Nitro. It will check for subdirectories, which will be registered
|
|
425
|
-
just like the
|
|
429
|
+
just like the `~~/server` folder is.
|
|
426
430
|
|
|
427
431
|
::note
|
|
428
|
-
Only
|
|
432
|
+
Only `~~/server/api`, `~~/server/routes`, `~~/server/middleware`, and `~~/server/utils` are scanned.
|
|
429
433
|
::
|
|
430
434
|
|
|
431
435
|
### Usage
|
|
@@ -24,7 +24,11 @@ Watch Vue School video about Auto-imports Nuxt Kit utilities.
|
|
|
24
24
|
|
|
25
25
|
## `addImports`
|
|
26
26
|
|
|
27
|
-
Add imports to the Nuxt application. It makes your imports available in the Nuxt
|
|
27
|
+
Add imports to the Nuxt application. It makes your imports available in the Nuxt app context without the need to import them manually.
|
|
28
|
+
|
|
29
|
+
::tip
|
|
30
|
+
To add imports for the Nitro server context, refer to the [`addServerImports`](/docs/3.x/api/kit/nitro#addserverimports) function.
|
|
31
|
+
::
|
|
28
32
|
|
|
29
33
|
### Usage
|
|
30
34
|
|
|
@@ -41,7 +41,7 @@ We recommend taking a look at [how to report bugs](/docs/3.x/community/reporting
|
|
|
41
41
|
|
|
42
42
|
## "I need professional help"
|
|
43
43
|
|
|
44
|
-
If the community couldn't provide the help you need in the time-frame you have, NuxtLabs offers professional support with the [Nuxt Experts](https://nuxt.com/enterprise/
|
|
44
|
+
If the community couldn't provide the help you need in the time-frame you have, NuxtLabs offers professional support with the [Nuxt Experts](https://nuxt.com/enterprise/agencies).
|
|
45
45
|
|
|
46
46
|
The objective of the Nuxt Expert is to provide support to the Vue ecosystem, while also creating freelance opportunities for those contributing to open-source solutions, thus helping to maintain the sustainability of the ecosystem.
|
|
47
47
|
|
package/5.community/6.roadmap.md
CHANGED
|
@@ -61,15 +61,15 @@ We commit to support each major version of Nuxt for a minimum of six months afte
|
|
|
61
61
|
|
|
62
62
|
The current active version of [Nuxt](https://nuxt.com) is **v4** which is available as `nuxt` on npm with the `latest` tag.
|
|
63
63
|
|
|
64
|
-
Nuxt 3 will continue to receive maintenance updates (
|
|
64
|
+
Nuxt 3 will continue to receive maintenance updates (bug fixes and security patches) until the end of July 2026.
|
|
65
65
|
|
|
66
66
|
Each active version has its own nightly releases which are generated automatically. For more about enabling the Nuxt nightly release channel, see [the nightly release channel docs](/docs/3.x/guide/going-further/nightly-release-channel).
|
|
67
67
|
|
|
68
68
|
| Release | | Initial release | End Of Life | Docs |
|
|
69
69
|
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|----------------------------|-------------------------------------------------------------------|
|
|
70
|
-
| **5.x** (scheduled) | |
|
|
71
|
-
| **4.x** (stable) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt latest version" src="https://img.shields.io/npm/v/nuxt.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2025-07-16 | 6 months after 5.x release | [nuxt.com](/docs/
|
|
72
|
-
| **3.x** (maintenance) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt 3.x version" src="https://img.shields.io/npm/v/nuxt/3x.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2022-11-16 | 2026-
|
|
70
|
+
| **5.x** (scheduled) | | Q1 2026 (estimated) | TBA | |
|
|
71
|
+
| **4.x** (stable) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt latest version" src="https://img.shields.io/npm/v/nuxt.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2025-07-16 | 6 months after 5.x release | [nuxt.com](/docs/4.x/getting-started/introduction) |
|
|
72
|
+
| **3.x** (maintenance) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt 3.x version" src="https://img.shields.io/npm/v/nuxt/3x.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2022-11-16 | 2026-07-31 | [nuxt.com](/docs/3.x/getting-started/introduction) |
|
|
73
73
|
| **2.x** (unsupported) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt 2.x version" src="https://img.shields.io/npm/v/nuxt/2x.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2018-09-21 | 2024-06-30 | [v2.nuxt.com](https://v2.nuxt.com/docs/get-started/installation/) |
|
|
74
74
|
| **1.x** (unsupported) | <a href="https://www.npmjs.com/package/nuxt?activeTab=versions"><img alt="Nuxt 1.x version" src="https://img.shields.io/npm/v/nuxt/1x.svg?logo=nuxt&label=&style=flat&colorA=18181B&colorB=28CF8D" class="not-prose h-5 w-auto" :zoom="false"></a> | 2018-01-08 | 2019-09-21 | |
|
|
75
75
|
|
package/7.migration/11.server.md
CHANGED
|
@@ -10,7 +10,7 @@ In a built Nuxt 3 application, there is no runtime Nuxt dependency. That means y
|
|
|
10
10
|
## Steps
|
|
11
11
|
|
|
12
12
|
1. Remove the `render` key in your `nuxt.config`.
|
|
13
|
-
2. Any files in
|
|
13
|
+
2. Any files in `~~/server/api` and `~~/server/middleware` will be automatically registered; you can remove them from your `serverMiddleware` array.
|
|
14
14
|
3. Update any other items in your `serverMiddleware` array to point to files or npm packages directly, rather than using inline functions.
|
|
15
15
|
|
|
16
16
|
:read-more{to="/docs/3.x/directory-structure/server"}
|