@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.
- package/1.getting-started/02.installation.md +3 -3
- package/1.getting-started/07.routing.md +4 -0
- package/1.getting-started/10.data-fetching.md +12 -12
- package/1.getting-started/14.layers.md +28 -9
- package/1.getting-started/18.upgrade.md +8 -4
- package/2.guide/1.directory-structure/1.node_modules.md +1 -1
- package/2.guide/1.directory-structure/3.tsconfig.md +23 -0
- package/2.guide/2.concepts/7.esm.md +5 -1
- package/2.guide/2.concepts/9.code-style.md +1 -1
- package/2.guide/3.going-further/1.experimental-features.md +92 -4
- package/2.guide/3.going-further/3.modules.md +36 -20
- package/2.guide/3.going-further/7.layers.md +44 -19
- package/2.guide/4.recipes/2.vite-plugin.md +41 -0
- package/3.api/1.components/13.nuxt-time.md +5 -1
- package/3.api/2.composables/use-async-data.md +80 -13
- package/3.api/2.composables/use-cookie.md +1 -1
- package/3.api/2.composables/use-fetch.md +5 -1
- package/3.api/2.composables/use-head-safe.md +37 -20
- package/3.api/2.composables/use-head.md +136 -36
- package/3.api/2.composables/use-hydration.md +24 -18
- package/3.api/2.composables/use-lazy-async-data.md +59 -10
- package/3.api/2.composables/use-lazy-fetch.md +66 -10
- package/3.api/2.composables/use-nuxt-app.md +1 -1
- package/3.api/2.composables/use-nuxt-data.md +1 -1
- package/3.api/2.composables/use-request-fetch.md +1 -1
- package/3.api/2.composables/use-route.md +1 -1
- package/3.api/2.composables/use-runtime-hook.md +1 -1
- package/3.api/3.utils/navigate-to.md +1 -1
- package/3.api/3.utils/refresh-cookie.md +2 -2
- package/3.api/5.kit/1.modules.md +88 -2
- package/3.api/5.kit/11.nitro.md +4 -0
- package/3.api/5.kit/14.builder.md +60 -4
- package/3.api/5.kit/15.examples.md +3 -5
- package/3.api/5.kit/2.programmatic.md +2 -2
- package/3.api/5.kit/5.components.md +1 -0
- package/3.api/5.kit/9.head.md +132 -0
- package/3.api/6.advanced/1.hooks.md +2 -2
- package/5.community/3.reporting-bugs.md +1 -1
- 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 (
|
|
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://
|
|
34
|
-
- **Windows slow DNS resolution
|
|
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
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
-
//
|
|
105
|
+
// Local layer outside the project
|
|
93
106
|
'../base',
|
|
94
|
-
//
|
|
107
|
+
// NPM package
|
|
95
108
|
'@my-themes/awesome',
|
|
96
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
|
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)
|
|
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 — 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
|
|
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
|
|
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
|
-
|
|
514
|
-
nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
|
|
509
|
+
const resolver = createResolver(import.meta.url)
|
|
515
510
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
83
|
-
'
|
|
84
|
-
//
|
|
85
|
-
'
|
|
86
|
-
//
|
|
87
|
-
'
|
|
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
|
|
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
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
|
252
|
-
- The user's project is the first item in the
|
|
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
|
```
|