mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(nuxt3): extends support for pages
& middleware
directories (#3783)
Co-authored-by: Pooya Parsa <pyapar@gmail.com>
This commit is contained in:
parent
29078bba74
commit
7c0d2e176c
3
examples/config-extends/base/middleware/foo.ts
Normal file
3
examples/config-extends/base/middleware/foo.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default defineNuxtRouteMiddleware(() => {
|
||||||
|
console.log('Hello from extended middleware !')
|
||||||
|
})
|
11
examples/config-extends/base/pages/foo.vue
Normal file
11
examples/config-extends/base/pages/foo.vue
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
Hello from extended page !
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'foo'
|
||||||
|
})
|
||||||
|
</script>
|
@ -12,15 +12,18 @@ export default defineNuxtModule({
|
|||||||
name: 'router'
|
name: 'router'
|
||||||
},
|
},
|
||||||
setup (_options, nuxt) {
|
setup (_options, nuxt) {
|
||||||
const pagesDir = resolve(nuxt.options.srcDir, nuxt.options.dir.pages)
|
const pagesDirs = nuxt.options._layers.map(
|
||||||
const runtimeDir = resolve(distDir, 'pages/runtime')
|
layer => resolve(layer.config.srcDir, layer.config.dir?.pages || 'pages')
|
||||||
|
)
|
||||||
|
|
||||||
// Disable module (and use universal router) if pages dir do not exists
|
// Disable module (and use universal router) if pages dir do not exists
|
||||||
if (!existsSync(pagesDir)) {
|
if (!pagesDirs.some(dir => existsSync(dir))) {
|
||||||
addPlugin(resolve(distDir, 'app/plugins/router'))
|
addPlugin(resolve(distDir, 'app/plugins/router'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runtimeDir = resolve(distDir, 'pages/runtime')
|
||||||
|
|
||||||
// Add $router types
|
// Add $router types
|
||||||
nuxt.hook('prepare:types', ({ references }) => {
|
nuxt.hook('prepare:types', ({ references }) => {
|
||||||
references.push({ types: 'vue-router' })
|
references.push({ types: 'vue-router' })
|
||||||
@ -68,7 +71,7 @@ export default defineNuxtModule({
|
|||||||
addTemplate({
|
addTemplate({
|
||||||
filename: 'routes.mjs',
|
filename: 'routes.mjs',
|
||||||
async getContents () {
|
async getContents () {
|
||||||
const pages = await resolvePagesRoutes(nuxt)
|
const pages = await resolvePagesRoutes()
|
||||||
await nuxt.callHook('pages:extend', pages)
|
await nuxt.callHook('pages:extend', pages)
|
||||||
const { routes, imports } = normalizeRoutes(pages)
|
const { routes, imports } = normalizeRoutes(pages)
|
||||||
return [...imports, `export default ${routes}`].join('\n')
|
return [...imports, `export default ${routes}`].join('\n')
|
||||||
@ -99,6 +102,7 @@ export default defineNuxtModule({
|
|||||||
filename: 'middleware.mjs',
|
filename: 'middleware.mjs',
|
||||||
async getContents () {
|
async getContents () {
|
||||||
const middleware = await resolveMiddleware()
|
const middleware = await resolveMiddleware()
|
||||||
|
await nuxt.callHook('pages:middleware:extend', middleware)
|
||||||
const globalMiddleware = middleware.filter(mw => mw.global)
|
const globalMiddleware = middleware.filter(mw => mw.global)
|
||||||
const namedMiddleware = middleware.filter(mw => !mw.global)
|
const namedMiddleware = middleware.filter(mw => !mw.global)
|
||||||
const namedMiddlewareObject = genObjectFromRawEntries(namedMiddleware.map(mw => [mw.name, genDynamicImport(mw.path)]))
|
const namedMiddlewareObject = genObjectFromRawEntries(namedMiddleware.map(mw => [mw.name, genDynamicImport(mw.path)]))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { basename, extname, normalize, relative, resolve } from 'pathe'
|
import { basename, extname, normalize, relative, resolve } from 'pathe'
|
||||||
import { encodePath } from 'ufo'
|
import { encodePath } from 'ufo'
|
||||||
import type { Nuxt, NuxtMiddleware, NuxtPage } from '@nuxt/schema'
|
import { NuxtMiddleware, NuxtPage } from '@nuxt/schema'
|
||||||
import { resolveFiles, useNuxt } from '@nuxt/kit'
|
import { resolveFiles, useNuxt } from '@nuxt/kit'
|
||||||
import { kebabCase, pascalCase } from 'scule'
|
import { kebabCase, pascalCase } from 'scule'
|
||||||
import { genImport, genDynamicImport, genArrayFromRaw } from 'knitwork'
|
import { genImport, genDynamicImport, genArrayFromRaw } from 'knitwork'
|
||||||
@ -24,14 +24,23 @@ interface SegmentToken {
|
|||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resolvePagesRoutes (nuxt: Nuxt) {
|
export async function resolvePagesRoutes (): Promise<NuxtPage[]> {
|
||||||
const pagesDir = resolve(nuxt.options.srcDir, nuxt.options.dir.pages)
|
const nuxt = useNuxt()
|
||||||
const files = await resolveFiles(pagesDir, `**/*{${nuxt.options.extensions.join(',')}}`)
|
|
||||||
|
|
||||||
// Sort to make sure parent are listed first
|
const pagesDirs = nuxt.options._layers.map(
|
||||||
files.sort()
|
layer => resolve(layer.config.srcDir, layer.config.dir?.pages || 'pages')
|
||||||
|
)
|
||||||
|
|
||||||
return generateRoutesFromFiles(files, pagesDir)
|
const allRoutes = (await Promise.all(
|
||||||
|
pagesDirs.map(async (dir) => {
|
||||||
|
const files = await resolveFiles(dir, `**/*{${nuxt.options.extensions.join(',')}}`)
|
||||||
|
// Sort to make sure parent are listed first
|
||||||
|
files.sort()
|
||||||
|
return generateRoutesFromFiles(files, dir)
|
||||||
|
})
|
||||||
|
)).flat()
|
||||||
|
|
||||||
|
return uniqueBy(allRoutes, 'name')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateRoutesFromFiles (files: string[], pagesDir: string): NuxtPage[] {
|
export function generateRoutesFromFiles (files: string[], pagesDir: string): NuxtPage[] {
|
||||||
@ -236,11 +245,19 @@ export function normalizeRoutes (routes: NuxtPage[], metaImports: Set<string> =
|
|||||||
|
|
||||||
export async function resolveMiddleware (): Promise<NuxtMiddleware[]> {
|
export async function resolveMiddleware (): Promise<NuxtMiddleware[]> {
|
||||||
const nuxt = useNuxt()
|
const nuxt = useNuxt()
|
||||||
const middlewareDir = resolve(nuxt.options.srcDir, nuxt.options.dir.middleware)
|
|
||||||
const files = await resolveFiles(middlewareDir, `*{${nuxt.options.extensions.join(',')}}`)
|
const middlewareDirs = nuxt.options._layers.map(
|
||||||
const middleware = files.map(path => ({ name: getNameFromPath(path), path, global: hasSuffix(path, '.global') }))
|
layer => resolve(layer.config.srcDir, layer.config.dir?.middleware || 'middleware')
|
||||||
await nuxt.callHook('pages:middleware:extend', middleware)
|
)
|
||||||
return middleware
|
|
||||||
|
const allMiddlewares = (await Promise.all(
|
||||||
|
middlewareDirs.map(async (dir) => {
|
||||||
|
const files = await resolveFiles(dir, `*{${nuxt.options.extensions.join(',')}}`)
|
||||||
|
return files.map(path => ({ name: getNameFromPath(path), path, global: hasSuffix(path, '.global') }))
|
||||||
|
})
|
||||||
|
)).flat()
|
||||||
|
|
||||||
|
return uniqueBy(allMiddlewares, 'name')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNameFromPath (path: string) {
|
function getNameFromPath (path: string) {
|
||||||
@ -254,3 +271,16 @@ function hasSuffix (path: string, suffix: string) {
|
|||||||
export function getImportName (name: string) {
|
export function getImportName (name: string) {
|
||||||
return pascalCase(name).replace(/[^\w]/g, '')
|
return pascalCase(name).replace(/[^\w]/g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uniqueBy (arr: any[], key: string) {
|
||||||
|
const res = []
|
||||||
|
const keys = new Set<string>()
|
||||||
|
for (const item of arr) {
|
||||||
|
if (keys.has(item[key])) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
keys.add(item[key])
|
||||||
|
res.push(item)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -2,158 +2,182 @@ import { fileURLToPath } from 'url'
|
|||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import { setup, $fetch, startServer } from '@nuxt/test-utils'
|
import { setup, $fetch, startServer } from '@nuxt/test-utils'
|
||||||
|
|
||||||
describe('fixtures:basic', async () => {
|
await setup({
|
||||||
await setup({
|
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
|
||||||
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
|
server: true
|
||||||
server: true
|
})
|
||||||
})
|
|
||||||
|
|
||||||
describe('server api', () => {
|
describe('server api', () => {
|
||||||
it('should serialize', async () => {
|
it('should serialize', async () => {
|
||||||
expect(await $fetch('/api/hello')).toBe('Hello API')
|
expect(await $fetch('/api/hello')).toBe('Hello API')
|
||||||
expect(await $fetch('/api/hey')).toEqual({
|
expect(await $fetch('/api/hey')).toEqual({
|
||||||
foo: 'bar',
|
foo: 'bar',
|
||||||
baz: 'qux'
|
baz: 'qux'
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should preserve states', async () => {
|
|
||||||
expect(await $fetch('/api/counter')).toEqual({ count: 0 })
|
|
||||||
expect(await $fetch('/api/counter')).toEqual({ count: 1 })
|
|
||||||
expect(await $fetch('/api/counter')).toEqual({ count: 2 })
|
|
||||||
expect(await $fetch('/api/counter')).toEqual({ count: 3 })
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should preserve states', async () => {
|
||||||
|
expect(await $fetch('/api/counter')).toEqual({ count: 0 })
|
||||||
|
expect(await $fetch('/api/counter')).toEqual({ count: 1 })
|
||||||
|
expect(await $fetch('/api/counter')).toEqual({ count: 2 })
|
||||||
|
expect(await $fetch('/api/counter')).toEqual({ count: 3 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('pages', () => {
|
||||||
|
it('render index', async () => {
|
||||||
|
const html = await $fetch('/')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
// should render text
|
||||||
|
expect(html).toContain('Hello Nuxt 3!')
|
||||||
|
// should render <Head> components
|
||||||
|
expect(html).toContain('<title>Basic fixture</title>')
|
||||||
|
// should inject runtime config
|
||||||
|
expect(html).toContain('RuntimeConfig | testConfig: 123')
|
||||||
|
// composables auto import
|
||||||
|
expect(html).toContain('Composable | foo: auto imported from ~/components/foo.ts')
|
||||||
|
expect(html).toContain('Composable | bar: auto imported from ~/components/useBar.ts')
|
||||||
|
// plugins
|
||||||
|
expect(html).toContain('Plugin | myPlugin: Injected by my-plugin')
|
||||||
|
// should import components
|
||||||
|
expect(html).toContain('This is a custom component with a named export.')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('render 404', async () => {
|
||||||
|
const html = await $fetch('/not-found')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('[...slug].vue')
|
||||||
|
expect(html).toContain('404 at not-found')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('/nested/[foo]/[bar].vue', async () => {
|
||||||
|
const html = await $fetch('/nested/one/two')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('nested/[foo]/[bar].vue')
|
||||||
|
expect(html).toContain('foo: one')
|
||||||
|
expect(html).toContain('bar: two')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('/nested/[foo]/index.vue', async () => {
|
||||||
|
const html = await $fetch('/nested/foobar')
|
||||||
|
|
||||||
|
// TODO: should resolved to same entry
|
||||||
|
// const html2 = await $fetch('/nested/foobar/index')
|
||||||
|
// expect(html).toEqual(html2)
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('nested/[foo]/index.vue')
|
||||||
|
expect(html).toContain('foo: foobar')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('/nested/[foo]/user-[group].vue', async () => {
|
||||||
|
const html = await $fetch('/nested/foobar/user-admin')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('nested/[foo]/user-[group].vue')
|
||||||
|
expect(html).toContain('foo: foobar')
|
||||||
|
expect(html).toContain('group: admin')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('navigate', () => {
|
||||||
|
it('should redirect to index with navigateTo', async () => {
|
||||||
|
const html = await $fetch('/navigate-to/')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('Hello Nuxt 3!')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('middlewares', () => {
|
||||||
|
it('should redirect to index with global middleware', async () => {
|
||||||
|
const html = await $fetch('/redirect/')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('Hello Nuxt 3!')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should inject auth', async () => {
|
||||||
|
const html = await $fetch('/auth')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('auth.vue')
|
||||||
|
expect(html).toContain('auth: Injected by injectAuth middleware')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not inject auth', async () => {
|
||||||
|
const html = await $fetch('/no-auth')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('no-auth.vue')
|
||||||
|
expect(html).toContain('auth: ')
|
||||||
|
expect(html).not.toContain('Injected by injectAuth middleware')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('layouts', () => {
|
||||||
|
it('should apply custom layout', async () => {
|
||||||
|
const html = await $fetch('/with-layout')
|
||||||
|
|
||||||
|
// Snapshot
|
||||||
|
// expect(html).toMatchInlineSnapshot()
|
||||||
|
|
||||||
|
expect(html).toContain('with-layout.vue')
|
||||||
|
expect(html).toContain('Custom Layout:')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('reactivity transform', () => {
|
||||||
|
it('should works', async () => {
|
||||||
|
const html = await $fetch('/')
|
||||||
|
|
||||||
|
expect(html).toContain('Sugar Counter 12 x 2 = 24')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('extends support', () => {
|
||||||
describe('pages', () => {
|
describe('pages', () => {
|
||||||
it('render index', async () => {
|
it('extends foo/pages/index.vue', async () => {
|
||||||
const html = await $fetch('/')
|
const html = await $fetch('/foo')
|
||||||
|
expect(html).toContain('Hello from extended page of foo!')
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
// should render text
|
|
||||||
expect(html).toContain('Hello Nuxt 3!')
|
|
||||||
// should render <Head> components
|
|
||||||
expect(html).toContain('<title>Basic fixture</title>')
|
|
||||||
// should inject runtime config
|
|
||||||
expect(html).toContain('RuntimeConfig | testConfig: 123')
|
|
||||||
// composables auto import
|
|
||||||
expect(html).toContain('Composable | foo: auto imported from ~/components/foo.ts')
|
|
||||||
expect(html).toContain('Composable | bar: auto imported from ~/components/useBar.ts')
|
|
||||||
// plugins
|
|
||||||
expect(html).toContain('Plugin | myPlugin: Injected by my-plugin')
|
|
||||||
// should import components
|
|
||||||
expect(html).toContain('This is a custom component with a named export.')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('render 404', async () => {
|
it('extends bar/pages/override.vue over foo/pages/override.vue', async () => {
|
||||||
const html = await $fetch('/not-found')
|
const html = await $fetch('/override')
|
||||||
|
expect(html).toContain('Extended page from bar')
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('[...slug].vue')
|
|
||||||
expect(html).toContain('404 at not-found')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('/nested/[foo]/[bar].vue', async () => {
|
|
||||||
const html = await $fetch('/nested/one/two')
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('nested/[foo]/[bar].vue')
|
|
||||||
expect(html).toContain('foo: one')
|
|
||||||
expect(html).toContain('bar: two')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('/nested/[foo]/index.vue', async () => {
|
|
||||||
const html = await $fetch('/nested/foobar')
|
|
||||||
|
|
||||||
// TODO: should resolved to same entry
|
|
||||||
// const html2 = await $fetch('/nested/foobar/index')
|
|
||||||
// expect(html).toEqual(html2)
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('nested/[foo]/index.vue')
|
|
||||||
expect(html).toContain('foo: foobar')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('/nested/[foo]/user-[group].vue', async () => {
|
|
||||||
const html = await $fetch('/nested/foobar/user-admin')
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('nested/[foo]/user-[group].vue')
|
|
||||||
expect(html).toContain('foo: foobar')
|
|
||||||
expect(html).toContain('group: admin')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('navigate', () => {
|
|
||||||
it('should redirect to index with navigateTo', async () => {
|
|
||||||
const html = await $fetch('/navigate-to/')
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('Hello Nuxt 3!')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('middlewares', () => {
|
describe('middlewares', () => {
|
||||||
it('should redirect to index with global middleware', async () => {
|
it('extends foo/middleware/foo', async () => {
|
||||||
const html = await $fetch('/redirect/')
|
const html = await $fetch('/with-middleware')
|
||||||
|
expect(html).toContain('Injected by extended middleware')
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('Hello Nuxt 3!')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should inject auth', async () => {
|
it('extends bar/middleware/override.vue over foo/middleware/override.vue', async () => {
|
||||||
const html = await $fetch('/auth')
|
const html = await $fetch('/with-middleware-override')
|
||||||
|
expect(html).toContain('Injected by extended middleware from bar')
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('auth.vue')
|
|
||||||
expect(html).toContain('auth: Injected by injectAuth middleware')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not inject auth', async () => {
|
|
||||||
const html = await $fetch('/no-auth')
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('no-auth.vue')
|
|
||||||
expect(html).toContain('auth: ')
|
|
||||||
expect(html).not.toContain('Injected by injectAuth middleware')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('layouts', () => {
|
|
||||||
it('should apply custom layout', async () => {
|
|
||||||
const html = await $fetch('/with-layout')
|
|
||||||
|
|
||||||
// Snapshot
|
|
||||||
// expect(html).toMatchInlineSnapshot()
|
|
||||||
|
|
||||||
expect(html).toContain('with-layout.vue')
|
|
||||||
expect(html).toContain('Custom Layout:')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('reactivity transform', () => {
|
|
||||||
it('should works', async () => {
|
|
||||||
const html = await $fetch('/')
|
|
||||||
|
|
||||||
expect(html).toContain('Sugar Counter 12 x 2 = 24')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
3
test/fixtures/basic/extends/bar/middleware/override.ts
vendored
Normal file
3
test/fixtures/basic/extends/bar/middleware/override.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default defineNuxtRouteMiddleware((to) => {
|
||||||
|
to.meta.override = 'Injected by extended middleware from bar'
|
||||||
|
})
|
3
test/fixtures/basic/extends/bar/nuxt.config.ts
vendored
Normal file
3
test/fixtures/basic/extends/bar/nuxt.config.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { defineNuxtConfig } from 'nuxt3'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({})
|
3
test/fixtures/basic/extends/bar/pages/override.vue
vendored
Normal file
3
test/fixtures/basic/extends/bar/pages/override.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div>Extended page from bar</div>
|
||||||
|
</template>
|
3
test/fixtures/basic/extends/foo/middleware/foo.ts
vendored
Normal file
3
test/fixtures/basic/extends/foo/middleware/foo.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default defineNuxtRouteMiddleware((to) => {
|
||||||
|
to.meta.foo = 'Injected by extended middleware'
|
||||||
|
})
|
3
test/fixtures/basic/extends/foo/middleware/override.ts
vendored
Normal file
3
test/fixtures/basic/extends/foo/middleware/override.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default defineNuxtRouteMiddleware((to) => {
|
||||||
|
to.meta.override = 'Injected by extended middleware from foo'
|
||||||
|
})
|
3
test/fixtures/basic/extends/foo/nuxt.config.ts
vendored
Normal file
3
test/fixtures/basic/extends/foo/nuxt.config.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { defineNuxtConfig } from 'nuxt3'
|
||||||
|
|
||||||
|
export default defineNuxtConfig({})
|
3
test/fixtures/basic/extends/foo/pages/foo.vue
vendored
Normal file
3
test/fixtures/basic/extends/foo/pages/foo.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div>Hello from extended page of foo!</div>
|
||||||
|
</template>
|
3
test/fixtures/basic/extends/foo/pages/override.vue
vendored
Normal file
3
test/fixtures/basic/extends/foo/pages/override.vue
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
<div>Extended page from foo</div>
|
||||||
|
</template>
|
9
test/fixtures/basic/extends/foo/pages/with-middleware-override.vue
vendored
Normal file
9
test/fixtures/basic/extends/foo/pages/with-middleware-override.vue
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'override'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>{{ $route.meta.override }}</div>
|
||||||
|
</template>
|
9
test/fixtures/basic/extends/foo/pages/with-middleware.vue
vendored
Normal file
9
test/fixtures/basic/extends/foo/pages/with-middleware.vue
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script setup>
|
||||||
|
definePageMeta({
|
||||||
|
middleware: 'foo'
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>{{ $route.meta.foo }}</div>
|
||||||
|
</template>
|
4
test/fixtures/basic/nuxt.config.ts
vendored
4
test/fixtures/basic/nuxt.config.ts
vendored
@ -4,6 +4,10 @@ import { addComponent } from '@nuxt/kit'
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
buildDir: process.env.NITRO_BUILD_DIR,
|
||||||
builder: process.env.TEST_WITH_WEBPACK ? 'webpack' : 'vite',
|
builder: process.env.TEST_WITH_WEBPACK ? 'webpack' : 'vite',
|
||||||
|
extends: [
|
||||||
|
'./extends/bar',
|
||||||
|
'./extends/foo'
|
||||||
|
],
|
||||||
nitro: {
|
nitro: {
|
||||||
output: { dir: process.env.NITRO_OUTPUT_DIR }
|
output: { dir: process.env.NITRO_OUTPUT_DIR }
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user