@nuxt/docs 3.19.3 → 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 (39) hide show
  1. package/1.getting-started/02.installation.md +3 -3
  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/1.getting-started/18.upgrade.md +8 -4
  6. package/2.guide/1.directory-structure/1.node_modules.md +1 -1
  7. package/2.guide/1.directory-structure/3.tsconfig.md +23 -0
  8. package/2.guide/2.concepts/7.esm.md +5 -1
  9. package/2.guide/2.concepts/9.code-style.md +1 -1
  10. package/2.guide/3.going-further/1.experimental-features.md +92 -4
  11. package/2.guide/3.going-further/3.modules.md +36 -20
  12. package/2.guide/3.going-further/7.layers.md +44 -19
  13. package/2.guide/4.recipes/2.vite-plugin.md +41 -0
  14. package/3.api/1.components/13.nuxt-time.md +5 -1
  15. package/3.api/2.composables/use-async-data.md +80 -13
  16. package/3.api/2.composables/use-cookie.md +1 -1
  17. package/3.api/2.composables/use-fetch.md +5 -1
  18. package/3.api/2.composables/use-head-safe.md +37 -20
  19. package/3.api/2.composables/use-head.md +136 -36
  20. package/3.api/2.composables/use-hydration.md +24 -18
  21. package/3.api/2.composables/use-lazy-async-data.md +59 -10
  22. package/3.api/2.composables/use-lazy-fetch.md +66 -10
  23. package/3.api/2.composables/use-nuxt-app.md +1 -1
  24. package/3.api/2.composables/use-nuxt-data.md +1 -1
  25. package/3.api/2.composables/use-request-fetch.md +1 -1
  26. package/3.api/2.composables/use-route.md +1 -1
  27. package/3.api/2.composables/use-runtime-hook.md +1 -1
  28. package/3.api/3.utils/navigate-to.md +1 -1
  29. package/3.api/3.utils/refresh-cookie.md +2 -2
  30. package/3.api/5.kit/1.modules.md +88 -2
  31. package/3.api/5.kit/11.nitro.md +4 -0
  32. package/3.api/5.kit/14.builder.md +60 -4
  33. package/3.api/5.kit/15.examples.md +3 -5
  34. package/3.api/5.kit/2.programmatic.md +2 -2
  35. package/3.api/5.kit/5.components.md +1 -0
  36. package/3.api/5.kit/9.head.md +132 -0
  37. package/3.api/6.advanced/1.hooks.md +2 -2
  38. package/5.community/3.reporting-bugs.md +1 -1
  39. package/package.json +1 -1
@@ -28,10 +28,10 @@ Or follow the steps below to set up a new Nuxt project on your computer.
28
28
  ::note
29
29
  ::details
30
30
  :summary[Additional notes for an optimal setup:]
31
- - **Node.js**: Make sure to use an even numbered version (18, 20, etc)
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**.
@@ -120,19 +120,23 @@ You can run all the codemods mentioned in this guide using the following `codemo
120
120
  ::code-group
121
121
 
122
122
  ```bash [npm]
123
- npx codemod@latest nuxt/4/migration-recipe
123
+ # Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
124
+ npx codemod@0.18.7 nuxt/4/migration-recipe
124
125
  ```
125
126
 
126
127
  ```bash [yarn]
127
- yarn dlx codemod@latest nuxt/4/migration-recipe
128
+ # Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
129
+ yarn dlx codemod@0.18.7 nuxt/4/migration-recipe
128
130
  ```
129
131
 
130
132
  ```bash [pnpm]
131
- pnpm dlx codemod@latest nuxt/4/migration-recipe
133
+ # Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
134
+ pnpm dlx codemod@0.18.7 nuxt/4/migration-recipe
132
135
  ```
133
136
 
134
137
  ```bash [bun]
135
- bun x codemod@latest nuxt/4/migration-recipe
138
+ # Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
139
+ bun x codemod@0.18.7 nuxt/4/migration-recipe
136
140
  ```
137
141
 
138
142
  ::
@@ -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
+ ```
@@ -50,6 +50,10 @@ When adding modules to your package, things were a little different. A sample li
50
50
 
51
51
  So in Nuxt 2, the bundler (webpack) would pull in the CJS file ('main') for the server build and use the ESM file ('module') for the client build.
52
52
 
53
+ ::note
54
+ The `module` field is a convention used by bundlers like webpack and Rollup, but is not recognized by Node.js itself. Node.js only uses the [`exports`](https://nodejs.org/api/packages.html#exports) and [`main`](https://nodejs.org/api/packages.html#main) fields for module resolution.
55
+ ::
56
+
53
57
  However, in recent Node.js LTS releases, it is now possible to [use native ESM module](https://nodejs.org/api/esm.html) within Node.js. That means that Node.js itself can process JavaScript using ESM syntax, although it doesn't do it by default. The two most common ways to enable ESM syntax are:
54
58
 
55
59
  - set `"type": "module"` within your `package.json` and keep using `.js` extension
@@ -59,7 +63,7 @@ This is what we do for Nuxt Nitro; we output a `.output/server/index.mjs` file.
59
63
 
60
64
  ### What Are Valid Imports in a Node.js Context?
61
65
 
62
- When you `import` a module rather than `require` it, Node.js resolves it differently. For example, when you import `sample-library`, Node.js will look not for the `main` but for the `exports` or `module` entry in that library's `package.json`.
66
+ When you `import` a module rather than `require` it, Node.js resolves it differently. For example, when you import `sample-library`, Node.js will look for the `exports` entry in that library's `package.json`, or fall back to the `main` entry if `exports` is not defined.
63
67
 
64
68
  This is also true of dynamic imports, like `const b = await import('sample-library')`.
65
69
 
@@ -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
@@ -71,6 +71,44 @@ export default defineNuxtConfig({
71
71
  })
72
72
  ```
73
73
 
74
+ ## extractAsyncDataHandlers
75
+
76
+ Extracts handler functions from `useAsyncData` and `useLazyAsyncData` calls into separate chunks for improved code splitting and caching efficiency.
77
+
78
+ ```ts twoslash [nuxt.config.ts]
79
+ export default defineNuxtConfig({
80
+ experimental: {
81
+ extractAsyncDataHandlers: true,
82
+ },
83
+ })
84
+ ```
85
+
86
+ This feature transforms inline handler functions into dynamically imported chunks:
87
+
88
+ ```vue
89
+ <!-- Before -->
90
+ <script setup>
91
+ const { data } = await useAsyncData('user', async () => {
92
+ return await $fetch('/api/user')
93
+ })
94
+ </script>
95
+ ```
96
+
97
+ ```vue
98
+ <!-- After transformation -->
99
+ <script setup>
100
+ const { data } = await useAsyncData('user', () =>
101
+ import('/generated-chunk.js').then(r => r.default()),
102
+ )
103
+ </script>
104
+ ```
105
+
106
+ The benefit of this transformation is that we can split out data fetching logic &mdash; while still allowing the code to be loaded if required.
107
+
108
+ ::important
109
+ This feature is only recommended for **static builds** with payload extraction, and where data does not need to be re-fetched at runtime.
110
+ ::
111
+
74
112
  ## emitRouteChunkError
75
113
 
76
114
  Emits `app:chunkError` hook when there is an error loading vite/webpack chunks. Default behavior is to perform a reload of the new route on navigation to a new route when a chunk fails to load.
@@ -359,12 +397,12 @@ should do this automatically for you.)
359
397
  // This would be unsafe in a dynamic page (e.g. `[slug].vue`) because the route slug makes a difference
360
398
  // to the data fetched, but Nuxt can't know that because it's not reflected in the key.
361
399
  const route = useRoute()
362
- const { data } = await useAsyncData(async () => {
363
- 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 })
364
402
  })
365
403
  // Instead, you should use a key that uniquely identifies the data fetched.
366
- const { data } = await useAsyncData(route.params.slug, async () => {
367
- 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 })
368
406
  })
369
407
  ```
370
408
 
@@ -721,3 +759,53 @@ export default defineNuxtConfig({
721
759
  },
722
760
  })
723
761
  ```
762
+
763
+ ## typescriptPlugin
764
+
765
+ Enable enhanced TypeScript developer experience with the `@dxup/nuxt` module.
766
+
767
+ This experimental plugin provides improved TypeScript integration and development tooling for better DX when working with TypeScript in Nuxt applications.
768
+
769
+ This flag is disabled by default, but you can enable this feature:
770
+
771
+ ```ts twoslash [nuxt.config.ts]
772
+ export default defineNuxtConfig({
773
+ experimental: {
774
+ typescriptPlugin: true,
775
+ },
776
+ })
777
+ ```
778
+
779
+ ::important
780
+ To use this feature, you need to:
781
+ - Have `typescript` installed as a dependency
782
+ - Configure VS Code to use your workspace TypeScript version (see [VS Code documentation](https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-the-workspace-version-of-typescript))
783
+ ::
784
+
785
+ ::read-more{icon="i-simple-icons-github" to="https://github.com/KazariEX/dxup" target="_blank"}
786
+ Learn more about **@dxup/nuxt**.
787
+ ::
788
+
789
+ ## viteEnvironmentApi
790
+
791
+ Enable Vite 6's new [Environment API](https://vite.dev/guide/api-environment) for improved build configuration and plugin architecture.
792
+
793
+ When you set `future.compatibilityVersion` to `5`, this feature is enabled by default. You can also enable it explicitly for testing:
794
+
795
+ ```ts twoslash [nuxt.config.ts]
796
+ export default defineNuxtConfig({
797
+ experimental: {
798
+ viteEnvironmentApi: true,
799
+ },
800
+ })
801
+ ```
802
+
803
+ The Vite Environment API provides better consistency between development and production builds, more granular control over environment-specific configuration, and improved performance.
804
+
805
+ ::important
806
+ Enabling this feature changes how Vite plugins are registered and configured. See the [Vite Environment API migration guide](/docs/4.x/getting-started/upgrade#migration-to-vite-environment-api) for details on updating your plugins.
807
+ ::
808
+
809
+ ::read-more{to="https://vite.dev/guide/api-environment" target="_blank"}
810
+ Learn more about Vite's Environment API.
811
+ ::
@@ -501,35 +501,51 @@ export default defineNuxtModule({
501
501
 
502
502
  #### Using Other Modules in Your Module
503
503
 
504
- If your module depends on other modules, you can add them by using Nuxt Kit's `installModule` utility. For example, if you wanted to use Nuxt Tailwind in your module, you could add it as below:
504
+ If your module depends on other modules, you can specify them using the `moduleDependencies` option. This provides a more robust way to handle module dependencies with version constraints and configuration merging:
505
505
 
506
506
  ```ts
507
- import { createResolver, defineNuxtModule, installModule } from '@nuxt/kit'
508
-
509
- export default defineNuxtModule<ModuleOptions>({
510
- async setup (options, nuxt) {
511
- const resolver = createResolver(import.meta.url)
507
+ import { createResolver, defineNuxtModule } from '@nuxt/kit'
512
508
 
513
- // We can inject our CSS file which includes Tailwind's directives
514
- nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
509
+ const resolver = createResolver(import.meta.url)
515
510
 
516
- await installModule('@nuxtjs/tailwindcss', {
517
- // module configuration
518
- exposeConfig: true,
519
- config: {
520
- darkMode: 'class',
521
- content: {
522
- files: [
523
- resolver.resolve('./runtime/components/**/*.{vue,mjs,ts}'),
524
- resolver.resolve('./runtime/*.{mjs,js,ts}'),
525
- ],
511
+ export default defineNuxtModule<ModuleOptions>({
512
+ meta: {
513
+ name: 'my-module',
514
+ },
515
+ moduleDependencies: {
516
+ '@nuxtjs/tailwindcss': {
517
+ // You can specify a version constraint for the module
518
+ version: '>=6',
519
+ // Any configuration that should override `nuxt.options`
520
+ overrides: {
521
+ exposeConfig: true,
522
+ },
523
+ // Any configuration that should be set. It will override module defaults but
524
+ // will not override any configuration set in `nuxt.options`
525
+ defaults: {
526
+ config: {
527
+ darkMode: 'class',
528
+ content: {
529
+ files: [
530
+ resolver.resolve('./runtime/components/**/*.{vue,mjs,ts}'),
531
+ resolver.resolve('./runtime/*.{mjs,js,ts}'),
532
+ ],
533
+ },
526
534
  },
527
535
  },
528
- })
536
+ },
537
+ },
538
+ setup (options, nuxt) {
539
+ // We can inject our CSS file which includes Tailwind's directives
540
+ nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
529
541
  },
530
542
  })
531
543
  ```
532
544
 
545
+ ::callout{type="info"}
546
+ The `moduleDependencies` option replaces the deprecated `installModule` function and ensures proper setup order and configuration merging.
547
+ ::
548
+
533
549
  #### Using Hooks
534
550
 
535
551
  [Lifecycle hooks](/docs/3.x/guide/going-further/hooks) allow you to expand almost every aspect of Nuxt. Modules can hook to them programmatically or through the `hooks` map in their definition.
@@ -758,7 +774,7 @@ An example of such a workflow is available on [the module starter](https://githu
758
774
 
759
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).
760
776
 
761
- 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"`.
762
778
 
763
779
  After that, you should be able to reference `my-module` like in any regular project.
764
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
 
@@ -234,22 +251,30 @@ export default defineNuxtConfig({
234
251
 
235
252
  ## Multi-Layer Support for Nuxt Modules
236
253
 
237
- You can use the internal array `nuxt.options._layers` to support custom multi-layer handling for your modules.
254
+ You can use the [`getLayerDirectories`](/docs/api/kit/layers#getlayerdirectories) utility from Nuxt Kit to support custom multi-layer handling for your modules.
238
255
 
239
256
  ```ts [modules/my-module.ts]
257
+ import { defineNuxtModule, getLayerDirectories } from 'nuxt/kit'
258
+
240
259
  export default defineNuxtModule({
241
260
  setup (_options, nuxt) {
242
- for (const layer of nuxt.options._layers) {
243
- // You can check for a custom directory existence to extend for each layer
244
- console.log('Custom extension for', layer.cwd, layer.config)
261
+ const layerDirs = getLayerDirectories()
262
+
263
+ for (const [index, layer] of layerDirs.entries()) {
264
+ console.log(`Layer ${index}:`)
265
+ console.log(` Root: ${layer.root}`)
266
+ console.log(` App: ${layer.app}`)
267
+ console.log(` Server: ${layer.server}`)
268
+ console.log(` Pages: ${layer.appPages}`)
269
+ // ... other directories
245
270
  }
246
271
  },
247
272
  })
248
273
  ```
249
274
 
250
275
  **Notes:**
251
- - Earlier items in the `_layers` array have higher priority and override later ones
252
- - The user's project is the first item in the `_layers` array
276
+ - Earlier items in the array have higher priority and override later ones
277
+ - The user's project is the first item in the array
253
278
 
254
279
  ## Going Deeper
255
280
 
@@ -63,3 +63,44 @@ import config from '~/data/hello.yaml'
63
63
  ```
64
64
 
65
65
  ::
66
+
67
+ ## Using Vite Plugins in Nuxt Modules
68
+
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
+
71
+ ```ts [modules/my-module.ts]
72
+ import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
73
+ import yaml from '@rollup/plugin-yaml'
74
+
75
+ export default defineNuxtModule({
76
+ setup () {
77
+ addVitePlugin(yaml())
78
+ },
79
+ })
80
+ ```
81
+
82
+ For environment-specific plugins in Nuxt 5+, use the `applyToEnvironment()` method:
83
+
84
+ ```ts [modules/my-module.ts]
85
+ import { addVitePlugin, defineNuxtModule } from '@nuxt/kit'
86
+
87
+ export default defineNuxtModule({
88
+ setup () {
89
+ addVitePlugin(() => ({
90
+ name: 'my-client-plugin',
91
+ applyToEnvironment (environment) {
92
+ return environment.name === 'client'
93
+ },
94
+ // Plugin configuration
95
+ }))
96
+ },
97
+ })
98
+ ```
99
+
100
+ ::important
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
+ ::
103
+
104
+ ::read-more{to="/docs/3.x/api/kit/builder#addviteplugin"}
105
+ Read more about `addVitePlugin` in the Nuxt Kit documentation.
106
+ ::
@@ -104,13 +104,17 @@ Enables relative time formatting using the Intl.RelativeTimeFormat API:
104
104
 
105
105
  When `relative` is set to `true`, the component also accepts properties from [Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat/RelativeTimeFormat):
106
106
 
107
+ ::warning
108
+ Due to `style` being a reserved prop, `relativeStyle` prop is used instead.
109
+ ::
110
+
107
111
  ```vue
108
112
  <template>
109
113
  <NuxtTime
110
114
  :datetime="Date.now() - 3 * 24 * 60 * 60 * 1000"
111
115
  relative
112
116
  numeric="auto"
113
- style="long"
117
+ relative-style="long"
114
118
  />
115
119
  </template>
116
120
  ```