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>
|
||||
<BaseButton>Base Button</BaseButton>
|
||||
<FancyButton>Fancy Button</FancyButton>
|
||||
<UIButton>UI Button</UIButton>
|
||||
<br>
|
||||
{{ foo }} {{ bar }}
|
||||
<br>
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { defineNuxtConfig } from 'nuxt3'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
extends: './base',
|
||||
extends: [
|
||||
'./ui',
|
||||
'./base'
|
||||
],
|
||||
publicRuntimeConfig: {
|
||||
theme: {
|
||||
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)
|
||||
}
|
||||
|
||||
// Mock _extends
|
||||
nuxt.options._extends = nuxt.options._extends || []
|
||||
// Mock _layers
|
||||
nuxt.options._layers = nuxt.options._layers || [{
|
||||
config: nuxt.options,
|
||||
cwd: nuxt.options.rootDir,
|
||||
configFile: nuxt.options._nuxtConfigFile
|
||||
}]
|
||||
|
||||
if (opts.nitro) {
|
||||
await setupNitroBridge()
|
||||
|
@ -14,7 +14,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxt/schema": "^3.0.0",
|
||||
"c12": "^0.1.4",
|
||||
"c12": "^0.2.0",
|
||||
"consola": "^2.15.3",
|
||||
"defu": "^5.0.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)
|
||||
}
|
||||
|
||||
nuxtConfig._extends = layers
|
||||
nuxtConfig._layers = layers.filter(layer => layer.configFile && !layer.configFile.endsWith('.nuxtrc'))
|
||||
|
||||
// Resolve and apply defaults
|
||||
return applyDefaults(NuxtConfigSchema, nuxtConfig) as NuxtOptions
|
||||
|
@ -93,10 +93,7 @@ export async function writeTypes (nitroContext: NitroContext) {
|
||||
}
|
||||
|
||||
async function _build (nitroContext: NitroContext) {
|
||||
const serverDirs = [
|
||||
...nitroContext._extends.map(layer => layer.serverDir),
|
||||
nitroContext._nuxt.serverDir
|
||||
]
|
||||
const serverDirs = nitroContext._layers.map(layer => layer.serverDir)
|
||||
|
||||
nitroContext.scannedMiddleware = (
|
||||
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
||||
@ -181,7 +178,7 @@ async function _watch (nitroContext: NitroContext) {
|
||||
let watcher = startRollupWatcher(nitroContext)
|
||||
|
||||
const serverDirs = [
|
||||
...nitroContext._extends.map(layer => layer.serverDir),
|
||||
...nitroContext._layers.map(layer => layer.serverDir),
|
||||
nitroContext._nuxt.serverDir
|
||||
]
|
||||
|
||||
|
@ -84,7 +84,7 @@ export interface NitroContext {
|
||||
runtimeDir: string
|
||||
hooks: Hookable<NitroHooks>
|
||||
},
|
||||
_extends: Array<{
|
||||
_layers: Array<{
|
||||
serverDir: string
|
||||
}>
|
||||
}
|
||||
@ -158,7 +158,7 @@ export function getNitroContext (nuxtOptions: NuxtOptions, input: NitroInput): N
|
||||
runtimeDir,
|
||||
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')
|
||||
}))
|
||||
}
|
||||
|
@ -40,14 +40,9 @@ export default defineNuxtModule<Partial<AutoImportsOptions>>({
|
||||
imports: options.imports
|
||||
})
|
||||
|
||||
// composables/ dirs
|
||||
let composablesDirs = [
|
||||
join(nuxt.options.srcDir, 'composables'),
|
||||
...options.dirs
|
||||
]
|
||||
|
||||
// Extend with layers
|
||||
for (const layer of nuxt.options._extends) {
|
||||
// composables/ dirs from all layers
|
||||
let composablesDirs = []
|
||||
for (const layer of nuxt.options._layers) {
|
||||
composablesDirs.push(resolve(layer.config.srcDir, 'composables'))
|
||||
for (const dir of (layer.config.autoImports?.dirs ?? [])) {
|
||||
composablesDirs.push(resolve(layer.config.srcDir, dir))
|
||||
|
@ -39,26 +39,25 @@ export default defineNuxtModule<ComponentsOptions>({
|
||||
}))
|
||||
}
|
||||
}
|
||||
if (dir && typeof dir === 'object') {
|
||||
return {
|
||||
...dir,
|
||||
path: resolve(cwd, resolveAlias(dir.path, {
|
||||
if (!dir) {
|
||||
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
|
||||
}))
|
||||
}
|
||||
}
|
||||
return []
|
||||
}))
|
||||
}
|
||||
|
||||
// Resolve dirs
|
||||
nuxt.hook('app:resolve', async () => {
|
||||
const allDirs = [
|
||||
...normalizeDirs(componentOptions.dirs, nuxt.options.srcDir),
|
||||
...nuxt.options._extends
|
||||
// components/ dirs from all layers
|
||||
const allDirs = nuxt.options._layers
|
||||
.map(layer => normalizeDirs(layer.config.components, layer.cwd))
|
||||
.flat()
|
||||
]
|
||||
|
||||
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')
|
||||
}
|
||||
|
||||
// Resolve layouts
|
||||
// Resolve layouts/ from all config layers
|
||||
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(',')}}`)
|
||||
for (const file of layoutFiles) {
|
||||
const name = getNameFromPath(file)
|
||||
@ -82,16 +82,19 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
||||
}
|
||||
|
||||
// Resolve plugins
|
||||
app.plugins = []
|
||||
for (const config of [...nuxt.options._extends.map(layer => layer.config), nuxt.options]) {
|
||||
app.plugins = [
|
||||
...nuxt.options.plugins.map(normalizePlugin)
|
||||
]
|
||||
for (const config of nuxt.options._layers.map(layer => layer.config)) {
|
||||
app.plugins.push(...[
|
||||
...config.plugins ?? [],
|
||||
...(config.plugins || []),
|
||||
...await resolveFiles(config.srcDir, [
|
||||
'plugins/*.{ts,js,mjs,cjs,mts,cts}',
|
||||
'plugins/*/index.*{ts,js,mjs,cjs,mts,cts}'
|
||||
])
|
||||
].map(plugin => normalizePlugin(plugin as NuxtPlugin)))
|
||||
}
|
||||
app.plugins = uniqueBy(app.plugins, 'src')
|
||||
|
||||
// Extend app
|
||||
await nuxt.callHook('app:resolve', app)
|
||||
@ -100,3 +103,15 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
||||
function getNameFromPath (path: string) {
|
||||
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 () => {
|
||||
const serverDirs = [
|
||||
...nitroDevContext._extends.map(layer => layer.serverDir),
|
||||
nitroDevContext._nuxt.serverDir
|
||||
]
|
||||
const serverDirs = nitroDevContext._layers.map(layer => layer.serverDir)
|
||||
|
||||
nitroDevContext.scannedMiddleware = (
|
||||
await Promise.all(serverDirs.map(async dir => await scanMiddleware(dir)))
|
||||
|
@ -19,7 +19,7 @@
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
"c12": "^0.1.4",
|
||||
"c12": "^0.2.0",
|
||||
"create-require": "^1.1.1",
|
||||
"defu": "^5.0.1",
|
||||
"jiti": "^1.13.0",
|
||||
|
@ -10,7 +10,7 @@ export interface NuxtConfig extends DeepPartial<ConfigSchema> {
|
||||
|
||||
/** Normalized Nuxt options available as `nuxt.options.*` */
|
||||
export interface NuxtOptions extends ConfigSchema {
|
||||
_extends: ResolvedConfig<NuxtConfig>[]
|
||||
_layers: ResolvedConfig<NuxtConfig>[]
|
||||
}
|
||||
|
||||
export interface PublicRuntimeConfig extends Record<string, any> { }
|
||||
|
19
yarn.lock
19
yarn.lock
@ -2914,7 +2914,7 @@ __metadata:
|
||||
"@nuxt/schema": ^3.0.0
|
||||
"@types/lodash.template": ^4
|
||||
"@types/semver": ^7
|
||||
c12: ^0.1.4
|
||||
c12: ^0.2.0
|
||||
consola: ^2.15.3
|
||||
defu: ^5.0.1
|
||||
globby: ^13.1.1
|
||||
@ -3084,7 +3084,7 @@ __metadata:
|
||||
dependencies:
|
||||
"@types/lodash.template": ^4
|
||||
"@types/semver": ^7
|
||||
c12: ^0.1.4
|
||||
c12: ^0.2.0
|
||||
create-require: ^1.1.1
|
||||
defu: ^5.0.1
|
||||
jiti: ^1.13.0
|
||||
@ -7061,6 +7061,21 @@ __metadata:
|
||||
languageName: node
|
||||
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":
|
||||
version: 6.7.12
|
||||
resolution: "cac@npm:6.7.12"
|
||||
|
Loading…
Reference in New Issue
Block a user