mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat!(nuxt3): use individual config layers for extending (#3717)
This commit is contained in:
parent
24259495b2
commit
b03cdb7114
@ -10,6 +10,7 @@ const bar = getBar()
|
|||||||
<pre>{{ JSON.stringify(themeConfig, null, 2) }}</pre>
|
<pre>{{ JSON.stringify(themeConfig, null, 2) }}</pre>
|
||||||
<BaseButton>Base Button</BaseButton>
|
<BaseButton>Base Button</BaseButton>
|
||||||
<FancyButton>Fancy Button</FancyButton>
|
<FancyButton>Fancy Button</FancyButton>
|
||||||
|
<UIButton>UI Button</UIButton>
|
||||||
<br>
|
<br>
|
||||||
{{ foo }} {{ bar }}
|
{{ foo }} {{ bar }}
|
||||||
<br>
|
<br>
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
import { defineNuxtConfig } from 'nuxt3'
|
import { defineNuxtConfig } from 'nuxt3'
|
||||||
|
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
extends: './base',
|
extends: [
|
||||||
|
'./ui',
|
||||||
|
'./base'
|
||||||
|
],
|
||||||
publicRuntimeConfig: {
|
publicRuntimeConfig: {
|
||||||
theme: {
|
theme: {
|
||||||
primaryColor: 'user_primary'
|
primaryColor: 'user_primary'
|
||||||
|
14
examples/config-extends/ui/components/Button.vue
Normal file
14
examples/config-extends/ui/components/Button.vue
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: 'black'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<button class="ui-button" :style="{ color }">
|
||||||
|
<slot />
|
||||||
|
</button>
|
||||||
|
</template>
|
7
examples/config-extends/ui/nuxt.config.ts
Normal file
7
examples/config-extends/ui/nuxt.config.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { defineNuxtConfig } from 'nuxt3'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
components: [
|
||||||
|
{ path: './components', prefix: 'UI' }
|
||||||
|
]
|
||||||
|
})
|
@ -41,8 +41,12 @@ export default defineNuxtModule({
|
|||||||
nuxtCtx.set(nuxt)
|
nuxtCtx.set(nuxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock _extends
|
// Mock _layers
|
||||||
nuxt.options._extends = nuxt.options._extends || []
|
nuxt.options._layers = nuxt.options._layers || [{
|
||||||
|
config: nuxt.options,
|
||||||
|
cwd: nuxt.options.rootDir,
|
||||||
|
configFile: nuxt.options._nuxtConfigFile
|
||||||
|
}]
|
||||||
|
|
||||||
if (opts.nitro) {
|
if (opts.nitro) {
|
||||||
await setupNitroBridge()
|
await setupNitroBridge()
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/schema": "^3.0.0",
|
"@nuxt/schema": "^3.0.0",
|
||||||
"c12": "^0.1.4",
|
"c12": "^0.2.0",
|
||||||
"consola": "^2.15.3",
|
"consola": "^2.15.3",
|
||||||
"defu": "^5.0.1",
|
"defu": "^5.0.1",
|
||||||
"globby": "^13.1.1",
|
"globby": "^13.1.1",
|
||||||
|
@ -44,7 +44,7 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise<Nuxt
|
|||||||
layer.config.srcDir = resolve(layer.config.rootDir, layer.config.srcDir)
|
layer.config.srcDir = resolve(layer.config.rootDir, layer.config.srcDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
nuxtConfig._extends = layers
|
nuxtConfig._layers = layers.filter(layer => layer.configFile && !layer.configFile.endsWith('.nuxtrc'))
|
||||||
|
|
||||||
// Resolve and apply defaults
|
// Resolve and apply defaults
|
||||||
return applyDefaults(NuxtConfigSchema, nuxtConfig) as NuxtOptions
|
return applyDefaults(NuxtConfigSchema, nuxtConfig) as NuxtOptions
|
||||||
|
@ -93,10 +93,7 @@ export async function writeTypes (nitroContext: NitroContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function _build (nitroContext: NitroContext) {
|
async function _build (nitroContext: NitroContext) {
|
||||||
const serverDirs = [
|
const serverDirs = nitroContext._layers.map(layer => layer.serverDir)
|
||||||
...nitroContext._extends.map(layer => layer.serverDir),
|
|
||||||
nitroContext._nuxt.serverDir
|
|
||||||
]
|
|
||||||
|
|
||||||
nitroContext.scannedMiddleware = (
|
nitroContext.scannedMiddleware = (
|
||||||
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
||||||
@ -181,7 +178,7 @@ async function _watch (nitroContext: NitroContext) {
|
|||||||
let watcher = startRollupWatcher(nitroContext)
|
let watcher = startRollupWatcher(nitroContext)
|
||||||
|
|
||||||
const serverDirs = [
|
const serverDirs = [
|
||||||
...nitroContext._extends.map(layer => layer.serverDir),
|
...nitroContext._layers.map(layer => layer.serverDir),
|
||||||
nitroContext._nuxt.serverDir
|
nitroContext._nuxt.serverDir
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ export interface NitroContext {
|
|||||||
runtimeDir: string
|
runtimeDir: string
|
||||||
hooks: Hookable<NitroHooks>
|
hooks: Hookable<NitroHooks>
|
||||||
},
|
},
|
||||||
_extends: Array<{
|
_layers: Array<{
|
||||||
serverDir: string
|
serverDir: string
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ export function getNitroContext (nuxtOptions: NuxtOptions, input: NitroInput): N
|
|||||||
runtimeDir,
|
runtimeDir,
|
||||||
hooks: createHooks<NitroHooks>()
|
hooks: createHooks<NitroHooks>()
|
||||||
},
|
},
|
||||||
_extends: nuxtOptions._extends.map(layer => ({
|
_layers: nuxtOptions._layers.map(layer => ({
|
||||||
serverDir: resolve(layer.config.srcDir, (layer.config.dir as any)?.server || 'server')
|
serverDir: resolve(layer.config.srcDir, (layer.config.dir as any)?.server || 'server')
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -40,14 +40,9 @@ export default defineNuxtModule<Partial<AutoImportsOptions>>({
|
|||||||
imports: options.imports
|
imports: options.imports
|
||||||
})
|
})
|
||||||
|
|
||||||
// composables/ dirs
|
// composables/ dirs from all layers
|
||||||
let composablesDirs = [
|
let composablesDirs = []
|
||||||
join(nuxt.options.srcDir, 'composables'),
|
for (const layer of nuxt.options._layers) {
|
||||||
...options.dirs
|
|
||||||
]
|
|
||||||
|
|
||||||
// Extend with layers
|
|
||||||
for (const layer of nuxt.options._extends) {
|
|
||||||
composablesDirs.push(resolve(layer.config.srcDir, 'composables'))
|
composablesDirs.push(resolve(layer.config.srcDir, 'composables'))
|
||||||
for (const dir of (layer.config.autoImports?.dirs ?? [])) {
|
for (const dir of (layer.config.autoImports?.dirs ?? [])) {
|
||||||
composablesDirs.push(resolve(layer.config.srcDir, dir))
|
composablesDirs.push(resolve(layer.config.srcDir, dir))
|
||||||
|
@ -39,26 +39,25 @@ export default defineNuxtModule<ComponentsOptions>({
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dir && typeof dir === 'object') {
|
if (!dir) {
|
||||||
return {
|
return []
|
||||||
...dir,
|
|
||||||
path: resolve(cwd, resolveAlias(dir.path, {
|
|
||||||
...nuxt.options.alias,
|
|
||||||
'~': cwd
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return []
|
const dirs = (dir.dirs || [dir]).filter(_dir => _dir.path)
|
||||||
|
return dirs.map(_dir => ({
|
||||||
|
..._dir,
|
||||||
|
path: resolve(cwd, resolveAlias(_dir.path, {
|
||||||
|
...nuxt.options.alias,
|
||||||
|
'~': cwd
|
||||||
|
}))
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve dirs
|
// Resolve dirs
|
||||||
nuxt.hook('app:resolve', async () => {
|
nuxt.hook('app:resolve', async () => {
|
||||||
const allDirs = [
|
// components/ dirs from all layers
|
||||||
...normalizeDirs(componentOptions.dirs, nuxt.options.srcDir),
|
const allDirs = nuxt.options._layers
|
||||||
...nuxt.options._extends
|
.map(layer => normalizeDirs(layer.config.components, layer.cwd))
|
||||||
.map(layer => normalizeDirs(layer.config.components, layer.cwd))
|
.flat()
|
||||||
.flat()
|
|
||||||
]
|
|
||||||
|
|
||||||
await nuxt.callHook('components:dirs', allDirs)
|
await nuxt.callHook('components:dirs', allDirs)
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
|||||||
app.errorComponent = (await findPath(['~/error'])) || resolve(nuxt.options.appDir, 'components/nuxt-error-page.vue')
|
app.errorComponent = (await findPath(['~/error'])) || resolve(nuxt.options.appDir, 'components/nuxt-error-page.vue')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve layouts
|
// Resolve layouts/ from all config layers
|
||||||
app.layouts = {}
|
app.layouts = {}
|
||||||
for (const config of [nuxt.options, ...nuxt.options._extends.map(layer => layer.config)]) {
|
for (const config of nuxt.options._layers.map(layer => layer.config)) {
|
||||||
const layoutFiles = await resolveFiles(config.srcDir, `${config.dir?.layouts || 'layouts'}/*{${nuxt.options.extensions.join(',')}}`)
|
const layoutFiles = await resolveFiles(config.srcDir, `${config.dir?.layouts || 'layouts'}/*{${nuxt.options.extensions.join(',')}}`)
|
||||||
for (const file of layoutFiles) {
|
for (const file of layoutFiles) {
|
||||||
const name = getNameFromPath(file)
|
const name = getNameFromPath(file)
|
||||||
@ -82,16 +82,19 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve plugins
|
// Resolve plugins
|
||||||
app.plugins = []
|
app.plugins = [
|
||||||
for (const config of [...nuxt.options._extends.map(layer => layer.config), nuxt.options]) {
|
...nuxt.options.plugins.map(normalizePlugin)
|
||||||
|
]
|
||||||
|
for (const config of nuxt.options._layers.map(layer => layer.config)) {
|
||||||
app.plugins.push(...[
|
app.plugins.push(...[
|
||||||
...config.plugins ?? [],
|
...(config.plugins || []),
|
||||||
...await resolveFiles(config.srcDir, [
|
...await resolveFiles(config.srcDir, [
|
||||||
'plugins/*.{ts,js,mjs,cjs,mts,cts}',
|
'plugins/*.{ts,js,mjs,cjs,mts,cts}',
|
||||||
'plugins/*/index.*{ts,js,mjs,cjs,mts,cts}'
|
'plugins/*/index.*{ts,js,mjs,cjs,mts,cts}'
|
||||||
])
|
])
|
||||||
].map(plugin => normalizePlugin(plugin as NuxtPlugin)))
|
].map(plugin => normalizePlugin(plugin as NuxtPlugin)))
|
||||||
}
|
}
|
||||||
|
app.plugins = uniqueBy(app.plugins, 'src')
|
||||||
|
|
||||||
// Extend app
|
// Extend app
|
||||||
await nuxt.callHook('app:resolve', app)
|
await nuxt.callHook('app:resolve', app)
|
||||||
@ -100,3 +103,15 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
|||||||
function getNameFromPath (path: string) {
|
function getNameFromPath (path: string) {
|
||||||
return kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '')
|
return kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uniqueBy (arr: any[], uniqueKey: string) {
|
||||||
|
const seen = new Set<string>()
|
||||||
|
const res = []
|
||||||
|
for (const i of arr) {
|
||||||
|
const key = i[uniqueKey]
|
||||||
|
if (seen.has(key)) { continue }
|
||||||
|
res.push(i)
|
||||||
|
seen.add(key)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -77,10 +77,7 @@ export function initNitro (nuxt: Nuxt) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
nuxt.hook('build:before', async () => {
|
nuxt.hook('build:before', async () => {
|
||||||
const serverDirs = [
|
const serverDirs = nitroDevContext._layers.map(layer => layer.serverDir)
|
||||||
...nitroDevContext._extends.map(layer => layer.serverDir),
|
|
||||||
nitroDevContext._nuxt.serverDir
|
|
||||||
]
|
|
||||||
|
|
||||||
nitroDevContext.scannedMiddleware = (
|
nitroDevContext.scannedMiddleware = (
|
||||||
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"unbuild": "latest"
|
"unbuild": "latest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"c12": "^0.1.4",
|
"c12": "^0.2.0",
|
||||||
"create-require": "^1.1.1",
|
"create-require": "^1.1.1",
|
||||||
"defu": "^5.0.1",
|
"defu": "^5.0.1",
|
||||||
"jiti": "^1.13.0",
|
"jiti": "^1.13.0",
|
||||||
|
@ -10,7 +10,7 @@ export interface NuxtConfig extends DeepPartial<ConfigSchema> {
|
|||||||
|
|
||||||
/** Normalized Nuxt options available as `nuxt.options.*` */
|
/** Normalized Nuxt options available as `nuxt.options.*` */
|
||||||
export interface NuxtOptions extends ConfigSchema {
|
export interface NuxtOptions extends ConfigSchema {
|
||||||
_extends: ResolvedConfig<NuxtConfig>[]
|
_layers: ResolvedConfig<NuxtConfig>[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PublicRuntimeConfig extends Record<string, any> { }
|
export interface PublicRuntimeConfig extends Record<string, any> { }
|
||||||
|
19
yarn.lock
19
yarn.lock
@ -2914,7 +2914,7 @@ __metadata:
|
|||||||
"@nuxt/schema": ^3.0.0
|
"@nuxt/schema": ^3.0.0
|
||||||
"@types/lodash.template": ^4
|
"@types/lodash.template": ^4
|
||||||
"@types/semver": ^7
|
"@types/semver": ^7
|
||||||
c12: ^0.1.4
|
c12: ^0.2.0
|
||||||
consola: ^2.15.3
|
consola: ^2.15.3
|
||||||
defu: ^5.0.1
|
defu: ^5.0.1
|
||||||
globby: ^13.1.1
|
globby: ^13.1.1
|
||||||
@ -3084,7 +3084,7 @@ __metadata:
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/lodash.template": ^4
|
"@types/lodash.template": ^4
|
||||||
"@types/semver": ^7
|
"@types/semver": ^7
|
||||||
c12: ^0.1.4
|
c12: ^0.2.0
|
||||||
create-require: ^1.1.1
|
create-require: ^1.1.1
|
||||||
defu: ^5.0.1
|
defu: ^5.0.1
|
||||||
jiti: ^1.13.0
|
jiti: ^1.13.0
|
||||||
@ -7061,6 +7061,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"c12@npm:^0.2.0":
|
||||||
|
version: 0.2.0
|
||||||
|
resolution: "c12@npm:0.2.0"
|
||||||
|
dependencies:
|
||||||
|
defu: ^5.0.1
|
||||||
|
dotenv: ^14.3.2
|
||||||
|
gittar: ^0.1.1
|
||||||
|
jiti: ^1.12.14
|
||||||
|
mlly: ^0.4.1
|
||||||
|
pathe: ^0.2.0
|
||||||
|
rc9: ^1.2.0
|
||||||
|
checksum: 1f69ed861368c8dc057f235a4925c4863b0423683a98578d3fa3c208dbcb43aadb907a5c855bf95969157210f632bfeb2bdf539f15a6c2d731d68f20273c00df
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cac@npm:^6.7.12":
|
"cac@npm:^6.7.12":
|
||||||
version: 6.7.12
|
version: 6.7.12
|
||||||
resolution: "cac@npm:6.7.12"
|
resolution: "cac@npm:6.7.12"
|
||||||
|
Loading…
Reference in New Issue
Block a user