@nuxt/docs-nightly 4.1.0-29279365.79d172b6 → 4.1.1-29280872.e12125a9
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.
|
@@ -27,6 +27,10 @@ modules[]=nuxt-security
|
|
|
27
27
|
|
|
28
28
|
If present, the properties in the `nuxt.config` file will overwrite the properties in `.nuxtrc` file.
|
|
29
29
|
|
|
30
|
+
::note
|
|
31
|
+
Nuxt automatically adds a `setups` section to track module installation and upgrade state. This is used internally for [module lifecycle hooks](/docs/api/kit/modules#using-lifecycle-hooks-for-module-installation-and-upgrade) and should not be modified manually.
|
|
32
|
+
::
|
|
33
|
+
|
|
30
34
|
::read-more{to="/docs/api/configuration/nuxt-config"}
|
|
31
35
|
Discover all the available options in the **Nuxt configuration** documentation.
|
|
32
36
|
::
|
|
@@ -780,6 +780,38 @@ Nuxt Modules should provide an explicit prefix for any exposed configuration, pl
|
|
|
780
780
|
|
|
781
781
|
Ideally, you should prefix them with your module's name (e.g. if your module is called `nuxt-foo`, expose `<FooButton>` and `useFooBar()` and **not** `<Button>` and `useBar()`).
|
|
782
782
|
|
|
783
|
+
#### Use Lifecycle Hooks for One-Time Setup
|
|
784
|
+
|
|
785
|
+
When your module needs to perform one-time setup tasks (like generating configuration files, setting up databases, or installing dependencies), use lifecycle hooks instead of running the logic in your main `setup` function.
|
|
786
|
+
|
|
787
|
+
```ts
|
|
788
|
+
import { addServerHandler, defineNuxtModule } from 'nuxt/kit'
|
|
789
|
+
import semver from 'semver'
|
|
790
|
+
|
|
791
|
+
export default defineNuxtModule({
|
|
792
|
+
meta: {
|
|
793
|
+
name: 'my-database-module',
|
|
794
|
+
version: '1.0.0',
|
|
795
|
+
},
|
|
796
|
+
async onInstall (nuxt) {
|
|
797
|
+
// One-time setup: create database schema, generate config files, etc.
|
|
798
|
+
await generateDatabaseConfig(nuxt.options.rootDir)
|
|
799
|
+
},
|
|
800
|
+
async onUpgrade (options, nuxt, previousVersion) {
|
|
801
|
+
// Handle version-specific migrations
|
|
802
|
+
if (semver.lt(previousVersion, '1.0.0')) {
|
|
803
|
+
await migrateLegacyData()
|
|
804
|
+
}
|
|
805
|
+
},
|
|
806
|
+
setup (options, nuxt) {
|
|
807
|
+
// Regular setup logic that runs on every build
|
|
808
|
+
addServerHandler({ /* ... */ })
|
|
809
|
+
},
|
|
810
|
+
})
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
This pattern prevents unnecessary work on every build and provides a better developer experience. See the [lifecycle hooks documentation](/docs/api/kit/modules#using-lifecycle-hooks-for-module-installation-and-upgrade) for more details.
|
|
814
|
+
|
|
783
815
|
#### Be TypeScript Friendly
|
|
784
816
|
|
|
785
817
|
Nuxt has first-class TypeScript integration for the best developer experience.
|
package/3.api/5.kit/1.modules.md
CHANGED
|
@@ -62,6 +62,8 @@ export function defineNuxtModule<TOptions extends ModuleOptions> (): {
|
|
|
62
62
|
| `defaults` | `T \| ((nuxt: Nuxt) => T)`{lang="ts"} | `false` | Default options for the module. If a function is provided, it will be called with the Nuxt instance as the first argument. |
|
|
63
63
|
| `schema` | `T` | `false` | Schema for the module options. If provided, options will be applied to the schema. |
|
|
64
64
|
| `hooks` | `Partial<NuxtHooks>`{lang="ts"} | `false` | Hooks to be installed for the module. If provided, the module will install the hooks. |
|
|
65
|
+
| `onInstall` | `(nuxt: Nuxt) => Awaitable<void>`{lang="ts"} | `false` | Lifecycle hook called when the module is first installed. Requires `meta.name` and `meta.version` to be defined. |
|
|
66
|
+
| `onUpgrade` | `(options: T, nuxt: Nuxt, previousVersion: string) => Awaitable<void>`{lang="ts"} | `false` | Lifecycle hook called when the module is upgraded to a newer version. Requires `meta.name` and `meta.version` to be defined. |
|
|
65
67
|
| `setup` | `(this: void, resolvedOptions: T, nuxt: Nuxt) => Awaitable<void \| false \| ModuleSetupInstallResult>`{lang="ts"} | `false` | Setup function for the module. If provided, the module will call the setup function. |
|
|
66
68
|
|
|
67
69
|
### Examples
|
|
@@ -171,6 +173,72 @@ export default defineNuxtModule<ModuleOptions>().with({
|
|
|
171
173
|
|
|
172
174
|
Without using `.with()`, the `resolvedOptions` parameter would be typed as the raw `ModuleOptions` interface, where `timeout` and `retries` could be `undefined` even when defaults are provided. The `.with()` method enables TypeScript to understand that default values make those properties non-optional in the resolved options.
|
|
173
175
|
|
|
176
|
+
#### Using Lifecycle Hooks for Module Installation and Upgrade
|
|
177
|
+
|
|
178
|
+
You can define lifecycle hooks that run when your module is first installed or upgraded to a new version. These hooks are useful for performing one-time setup tasks, database migrations, or cleanup operations.
|
|
179
|
+
|
|
180
|
+
::important
|
|
181
|
+
For lifecycle hooks to work, you **must** provide both `meta.name` and `meta.version` in your module definition. The hooks use these values to track the module's installation state in the project's `.nuxtrc` file.
|
|
182
|
+
::
|
|
183
|
+
|
|
184
|
+
Lifecycle hooks run before the main `setup` function, and if a hook throws an error, it's logged but doesn't stop the build process.
|
|
185
|
+
|
|
186
|
+
**`onInstall`** runs only once when the module is first added to a project.
|
|
187
|
+
|
|
188
|
+
**`onUpgrade`** runs each time the module version increases (using semver comparison) — but only once for each version bump.
|
|
189
|
+
|
|
190
|
+
##### Example
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
import { defineNuxtModule } from '@nuxt/kit'
|
|
194
|
+
import semver from 'semver'
|
|
195
|
+
|
|
196
|
+
export default defineNuxtModule({
|
|
197
|
+
meta: {
|
|
198
|
+
name: 'my-awesome-module',
|
|
199
|
+
version: '1.2.0', // Required for lifecycle hooks
|
|
200
|
+
configKey: 'myAwesomeModule'
|
|
201
|
+
},
|
|
202
|
+
defaults: {
|
|
203
|
+
apiKey: '',
|
|
204
|
+
enabled: true
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
onInstall(nuxt) {
|
|
208
|
+
// This runs only when the module is first installed
|
|
209
|
+
console.log('Setting up my-awesome-module for the first time!')
|
|
210
|
+
|
|
211
|
+
// You might want to:
|
|
212
|
+
// - Create initial configuration files
|
|
213
|
+
// - Set up database schemas
|
|
214
|
+
// - Display welcome messages
|
|
215
|
+
// - Perform initial data migration
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
onUpgrade(options, nuxt, previousVersion) {
|
|
219
|
+
// This runs when the module is upgraded to a newer version
|
|
220
|
+
console.log(`Upgrading my-awesome-module from ${previousVersion} to 1.2.0`)
|
|
221
|
+
|
|
222
|
+
// You might want to:
|
|
223
|
+
// - Migrate configuration files
|
|
224
|
+
// - Update database schemas
|
|
225
|
+
// - Clean up deprecated files
|
|
226
|
+
// - Display upgrade notes
|
|
227
|
+
|
|
228
|
+
if (semver.lt(previousVersion, '1.1.0')) {
|
|
229
|
+
console.log('⚠️ Breaking changes in 1.1.0 - please check the migration guide')
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
|
|
233
|
+
setup(options, nuxt) {
|
|
234
|
+
// Regular setup logic runs on every build
|
|
235
|
+
if (options.enabled) {
|
|
236
|
+
// Configure the module
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
```
|
|
241
|
+
|
|
174
242
|
## `installModule`
|
|
175
243
|
|
|
176
244
|
Install specified Nuxt module programmatically. This is helpful when your module depends on other modules. You can pass the module options as an object to `inlineOptions` and they will be passed to the module's `setup` function.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Layers"
|
|
3
|
+
description: Nuxt Kit provides utilities to help you work with layers and their directory structures.
|
|
4
|
+
links:
|
|
5
|
+
- label: Source
|
|
6
|
+
icon: i-simple-icons-github
|
|
7
|
+
to: https://github.com/nuxt/nuxt/blob/main/packages/kit/src/layers.ts
|
|
8
|
+
size: xs
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Nuxt layers provide a powerful way to share and extend functionality across projects. When working with layers in modules, you often need to access directory paths from each layer. Nuxt Kit provides the `getLayerDirectories` utility to access resolved directory paths for all layers in your Nuxt application.
|
|
12
|
+
|
|
13
|
+
## `getLayerDirectories`
|
|
14
|
+
|
|
15
|
+
Get the resolved directory paths for all layers in a Nuxt application. This function provides a structured way to access layer directories without directly accessing the private `nuxt.options._layers` property.
|
|
16
|
+
|
|
17
|
+
### Usage
|
|
18
|
+
|
|
19
|
+
```ts twoslash
|
|
20
|
+
import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
|
|
21
|
+
|
|
22
|
+
export default defineNuxtModule({
|
|
23
|
+
setup() {
|
|
24
|
+
const layerDirs = getLayerDirectories()
|
|
25
|
+
|
|
26
|
+
// Access directories from all layers
|
|
27
|
+
for (const [index, layer] of layerDirs.entries()) {
|
|
28
|
+
console.log(`Layer ${index}:`)
|
|
29
|
+
console.log(` Root: ${layer.root}`)
|
|
30
|
+
console.log(` App: ${layer.app}`)
|
|
31
|
+
console.log(` Server: ${layer.server}`)
|
|
32
|
+
console.log(` Pages: ${layer.appPages}`)
|
|
33
|
+
// ... other directories
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Type
|
|
40
|
+
|
|
41
|
+
```ts twoslash
|
|
42
|
+
// @errors: 2391
|
|
43
|
+
import type { Nuxt } from '@nuxt/schema'
|
|
44
|
+
// ---cut---
|
|
45
|
+
function getLayerDirectories(nuxt?: Nuxt): LayerDirectories[]
|
|
46
|
+
|
|
47
|
+
interface LayerDirectories {
|
|
48
|
+
/** Nuxt rootDir (`/` by default) */
|
|
49
|
+
readonly root: string
|
|
50
|
+
/** Nitro source directory (`/server` by default) */
|
|
51
|
+
readonly server: string
|
|
52
|
+
/** Local modules directory (`/modules` by default) */
|
|
53
|
+
readonly modules: string
|
|
54
|
+
/** Shared directory (`/shared` by default) */
|
|
55
|
+
readonly shared: string
|
|
56
|
+
/** Public directory (`/public` by default) */
|
|
57
|
+
readonly public: string
|
|
58
|
+
/** Nuxt srcDir (`/app/` by default) */
|
|
59
|
+
readonly app: string
|
|
60
|
+
/** Layouts directory (`/app/layouts` by default) */
|
|
61
|
+
readonly appLayouts: string
|
|
62
|
+
/** Middleware directory (`/app/middleware` by default) */
|
|
63
|
+
readonly appMiddleware: string
|
|
64
|
+
/** Pages directory (`/app/pages` by default) */
|
|
65
|
+
readonly appPages: string
|
|
66
|
+
/** Plugins directory (`/app/plugins` by default) */
|
|
67
|
+
readonly appPlugins: string
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Parameters
|
|
72
|
+
|
|
73
|
+
**`nuxt`** (optional): The Nuxt instance to get layers from. If not provided, the function will use the current Nuxt context.
|
|
74
|
+
|
|
75
|
+
### Return Value
|
|
76
|
+
|
|
77
|
+
The `getLayerDirectories` function returns an array of `LayerDirectories` objects, one for each layer in the application.
|
|
78
|
+
|
|
79
|
+
**Layer Priority Ordering**: The layers are ordered by priority, where:
|
|
80
|
+
- The **first layer** is the user/project layer (highest priority)
|
|
81
|
+
- **Earlier layers override later layers** in the array
|
|
82
|
+
- **Base layers appear last** in the array (lowest priority)
|
|
83
|
+
|
|
84
|
+
This ordering matches Nuxt's layer resolution system, where user-defined configurations and files take precedence over those from base layers.
|
|
85
|
+
|
|
86
|
+
**`LayerDirectories`**: An object containing the resolved directory paths for a layer.
|
|
87
|
+
|
|
88
|
+
| Property | Type | Description |
|
|
89
|
+
| --------------- | -------- | ------------------------------------------------------------------------------ |
|
|
90
|
+
| `root` | `string` | The root directory of the layer (equivalent to `rootDir`) |
|
|
91
|
+
| `server` | `string` | The server directory for Nitro server-side code |
|
|
92
|
+
| `modules` | `string` | The local modules directory |
|
|
93
|
+
| `shared` | `string` | The shared directory for code used by both client and server |
|
|
94
|
+
| `app` | `string` | The source directory of the layer (equivalent to `srcDir`) |
|
|
95
|
+
| `public` | `string` | The public directory for static assets |
|
|
96
|
+
| `appLayouts` | `string` | The layouts directory for Vue layout components |
|
|
97
|
+
| `appMiddleware` | `string` | The middleware directory for route middleware |
|
|
98
|
+
| `appPages` | `string` | The pages directory for file-based routing |
|
|
99
|
+
| `appPlugins` | `string` | The plugins directory for Nuxt plugins |
|
|
100
|
+
|
|
101
|
+
### Examples
|
|
102
|
+
|
|
103
|
+
**Processing files from all layers:**
|
|
104
|
+
|
|
105
|
+
```ts twoslash
|
|
106
|
+
// @errors: 2307
|
|
107
|
+
// ---cut---
|
|
108
|
+
import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
|
|
109
|
+
import { resolve } from 'pathe'
|
|
110
|
+
import { globby } from 'globby'
|
|
111
|
+
|
|
112
|
+
export default defineNuxtModule({
|
|
113
|
+
async setup() {
|
|
114
|
+
const layerDirs = getLayerDirectories()
|
|
115
|
+
|
|
116
|
+
// Find all component files across layers
|
|
117
|
+
// Note: layerDirs[0] is the user layer (highest priority)
|
|
118
|
+
// Later layers in the array have lower priority
|
|
119
|
+
const componentFiles = []
|
|
120
|
+
for (const [index, layer] of layerDirs.entries()) {
|
|
121
|
+
const files = await globby('**/*.vue', {
|
|
122
|
+
cwd: resolve(layer.app, 'components'),
|
|
123
|
+
absolute: true
|
|
124
|
+
})
|
|
125
|
+
console.log(`Layer ${index} (${index === 0 ? 'user' : 'base'}):`, files.length, 'components')
|
|
126
|
+
componentFiles.push(...files)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Adding templates from multiple layers:**
|
|
133
|
+
|
|
134
|
+
```ts twoslash
|
|
135
|
+
import { defineNuxtModule, getLayerDirectories, addTemplate } from '@nuxt/kit'
|
|
136
|
+
import { resolve, basename } from 'pathe'
|
|
137
|
+
import { existsSync } from 'fs'
|
|
138
|
+
|
|
139
|
+
export default defineNuxtModule({
|
|
140
|
+
async setup() {
|
|
141
|
+
const layerDirs = getLayerDirectories()
|
|
142
|
+
|
|
143
|
+
// Add a config file from each layer that has one
|
|
144
|
+
for (const dirs of layerDirs) {
|
|
145
|
+
const configPath = resolve(dirs.app, 'my-module.config.ts')
|
|
146
|
+
if (existsSync(configPath)) {
|
|
147
|
+
addTemplate({
|
|
148
|
+
filename: `my-module-${basename(dirs.root)}.config.ts`,
|
|
149
|
+
src: configPath
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Respecting layer priority:**
|
|
158
|
+
|
|
159
|
+
```ts twoslash
|
|
160
|
+
import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
|
|
161
|
+
import { resolve } from 'pathe'
|
|
162
|
+
import { existsSync, readFileSync } from 'fs'
|
|
163
|
+
|
|
164
|
+
export default defineNuxtModule({
|
|
165
|
+
setup() {
|
|
166
|
+
const layerDirs = getLayerDirectories()
|
|
167
|
+
|
|
168
|
+
// Find the first (highest priority) layer that has a specific config file
|
|
169
|
+
// This respects the layer priority system
|
|
170
|
+
let configContent = null
|
|
171
|
+
for (const dirs of layerDirs) {
|
|
172
|
+
const configPath = resolve(dirs.app, 'my-config.json')
|
|
173
|
+
if (existsSync(configPath)) {
|
|
174
|
+
configContent = readFileSync(configPath, 'utf-8')
|
|
175
|
+
console.log(`Using config from layer: ${dirs.root}`)
|
|
176
|
+
break // Use the first (highest priority) config found
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Alternative: Collect configs from all layers, with user layer taking precedence
|
|
181
|
+
const allConfigs = {}
|
|
182
|
+
for (const dirs of layerDirs.reverse()) { // Process from lowest to highest priority
|
|
183
|
+
const configPath = resolve(dirs.app, 'my-config.json')
|
|
184
|
+
if (existsSync(configPath)) {
|
|
185
|
+
const config = JSON.parse(readFileSync(configPath, 'utf-8'))
|
|
186
|
+
Object.assign(allConfigs, config) // Later assignments override earlier ones
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**Checking for layer-specific directories:**
|
|
194
|
+
|
|
195
|
+
```ts twoslash
|
|
196
|
+
import { defineNuxtModule, getLayerDirectories } from '@nuxt/kit'
|
|
197
|
+
import { existsSync } from 'fs'
|
|
198
|
+
import { resolve } from 'pathe'
|
|
199
|
+
|
|
200
|
+
export default defineNuxtModule({
|
|
201
|
+
setup() {
|
|
202
|
+
const layerDirs = getLayerDirectories()
|
|
203
|
+
|
|
204
|
+
// Find layers that have a specific custom directory
|
|
205
|
+
const layersWithAssets = layerDirs.filter(layer => {
|
|
206
|
+
return existsSync(resolve(layer.app, 'assets'))
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
console.log(`Found ${layersWithAssets.length} layers with assets directory`)
|
|
210
|
+
}
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
::note
|
|
215
|
+
The `getLayerDirectories` function includes caching via a WeakMap to avoid recomputing directory paths for the same layers repeatedly, improving performance when called multiple times.
|
|
216
|
+
::
|
|
217
|
+
|
|
218
|
+
::note
|
|
219
|
+
Directory paths returned by this function always include a trailing slash for consistency.
|
|
220
|
+
::
|