fix(nuxt): skip scanning layout/middleware without name (#25015)

This commit is contained in:
Daniel Roe 2024-01-02 22:04:26 +00:00 committed by GitHub
parent 7bd1ade096
commit b784336f8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 4 deletions

View File

@ -1,5 +1,5 @@
import { promises as fsp, mkdirSync, writeFileSync } from 'node:fs' import { promises as fsp, mkdirSync, writeFileSync } from 'node:fs'
import { dirname, join, resolve } from 'pathe' import { dirname, join, relative, resolve } from 'pathe'
import { defu } from 'defu' import { defu } from 'defu'
import { compileTemplate, findPath, logger, normalizePlugin, normalizeTemplate, resolveAlias, resolveFiles, resolvePath, templateUtils, tryResolveModule } from '@nuxt/kit' import { compileTemplate, findPath, logger, normalizePlugin, normalizeTemplate, resolveAlias, resolveFiles, resolvePath, templateUtils, tryResolveModule } from '@nuxt/kit'
import type { Nuxt, NuxtApp, NuxtPlugin, NuxtTemplate, ResolvedNuxtTemplate } from 'nuxt/schema' import type { Nuxt, NuxtApp, NuxtPlugin, NuxtTemplate, ResolvedNuxtTemplate } from 'nuxt/schema'
@ -117,6 +117,11 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
const layoutFiles = await resolveFiles(config.srcDir, `${layoutDir}/**/*{${nuxt.options.extensions.join(',')}}`) const layoutFiles = await resolveFiles(config.srcDir, `${layoutDir}/**/*{${nuxt.options.extensions.join(',')}}`)
for (const file of layoutFiles) { for (const file of layoutFiles) {
const name = getNameFromPath(file, resolve(config.srcDir, layoutDir)) const name = getNameFromPath(file, resolve(config.srcDir, layoutDir))
if (!name) {
// Ignore files like `~/layouts/index.vue` which end up not having a name at all
logger.warn(`No layout name could not be resolved for \`~/${relative(nuxt.options.srcDir, file)}\`. Bear in mind that \`index\` is ignored for the purpose of creating a layout name.`)
continue
}
app.layouts[name] = app.layouts[name] || { name, file } app.layouts[name] = app.layouts[name] || { name, file }
} }
} }
@ -126,10 +131,15 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
for (const config of reversedConfigs) { for (const config of reversedConfigs) {
const middlewareDir = (config.rootDir === nuxt.options.rootDir ? nuxt.options : config).dir?.middleware || 'middleware' const middlewareDir = (config.rootDir === nuxt.options.rootDir ? nuxt.options : config).dir?.middleware || 'middleware'
const middlewareFiles = await resolveFiles(config.srcDir, `${middlewareDir}/*{${nuxt.options.extensions.join(',')}}`) const middlewareFiles = await resolveFiles(config.srcDir, `${middlewareDir}/*{${nuxt.options.extensions.join(',')}}`)
app.middleware.push(...middlewareFiles.map((file) => { for (const file of middlewareFiles) {
const name = getNameFromPath(file) const name = getNameFromPath(file)
return { name, path: file, global: hasSuffix(file, '.global') } if (!name) {
})) // Ignore files like `~/middleware/index.vue` which end up not having a name at all
logger.warn(`No middleware name could not be resolved for \`~/${relative(nuxt.options.srcDir, file)}\`. Bear in mind that \`index\` is ignored for the purpose of creating a middleware name.`)
continue
}
app.middleware.push({ name, path: file, global: hasSuffix(file, '.global') })
}
} }
// Resolve plugins, first extended layers and then base // Resolve plugins, first extended layers and then base

View File

@ -80,6 +80,39 @@ describe('resolveApp', () => {
`) `)
}) })
it('resolves layouts and middleware correctly', async () => {
const app = await getResolvedApp([
'middleware/index.ts',
'middleware/auth/index.ts',
'middleware/other.ts',
'layouts/index.vue',
'layouts/default/index.vue',
'layouts/other.vue',
])
// Middleware are not resolved in a nested manner
expect(app.middleware.filter(m => m.path.startsWith('<rootDir>'))).toMatchInlineSnapshot(`
[
{
"global": false,
"name": "other",
"path": "<rootDir>/middleware/other.ts",
},
]
`)
expect(app.layouts).toMatchInlineSnapshot(`
{
"default": {
"file": "<rootDir>/layouts/default/index.vue",
"name": "default",
},
"other": {
"file": "<rootDir>/layouts/other.vue",
"name": "other",
},
}
`)
})
it('resolves layer plugins in correct order', async () => { it('resolves layer plugins in correct order', async () => {
const app = await getResolvedApp([ const app = await getResolvedApp([
// layer 1 // layer 1