diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index 63859a7b30..25d5c95ab9 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -12,7 +12,7 @@ import type { EditableTreeNode, Options as TypedRouterOptions } from 'unplugin-v import type { NitroRouteConfig } from 'nitropack' import { defu } from 'defu' import { distDir } from '../dirs' -import { normalizeRoutes, resolvePagesRoutes } from './utils' +import { normalizeRoutes, resolvePagesRoutes, resolveRoutePaths } from './utils' import { extractRouteRules, getMappedPages } from './route-rules' import type { PageMetaPluginOptions } from './plugins/page-meta' import { PageMetaPlugin } from './plugins/page-meta' @@ -371,9 +371,13 @@ export default defineNuxtModule({ // when the app manifest is enabled. nuxt.hook('pages:extend', (routes) => { const nitro = useNitro() + let resolvedRoutes: string[] for (const path in nitro.options.routeRules) { const rule = nitro.options.routeRules[path] if (!rule.redirect) { continue } + resolvedRoutes ||= routes.flatMap(route => resolveRoutePaths(route)) + // skip if there's already a route matching this path + if (resolvedRoutes.includes(path)) { continue } routes.push({ _sync: true, path: path.replace(/\/[^/]*\*\*/, '/:pathMatch(.*)'), diff --git a/packages/nuxt/src/pages/utils.ts b/packages/nuxt/src/pages/utils.ts index 28ece519e6..1d7b750fae 100644 --- a/packages/nuxt/src/pages/utils.ts +++ b/packages/nuxt/src/pages/utils.ts @@ -539,3 +539,10 @@ export function pathToNitroGlob (path: string) { return path.replace(/\/(?:[^:/]+)?:\w+.*$/, '/**') } + +export function resolveRoutePaths (page: NuxtPage, parent = '/'): string[] { + return [ + joinURL(parent, page.path), + ...page.children?.flatMap(child => resolveRoutePaths(child, joinURL(parent, page.path))) || [] + ] +} diff --git a/test/fixtures/basic-types/nuxt.config.ts b/test/fixtures/basic-types/nuxt.config.ts index 64719eea3b..e5b56da9ad 100644 --- a/test/fixtures/basic-types/nuxt.config.ts +++ b/test/fixtures/basic-types/nuxt.config.ts @@ -30,6 +30,11 @@ export default defineNuxtConfig({ val: 1 } }, + routeRules: { + '/param': { + redirect: '/param/1' + } + }, modules: [ function () { addTypeTemplate({ diff --git a/test/fixtures/basic-types/pages/param.vue b/test/fixtures/basic-types/pages/param.vue new file mode 100644 index 0000000000..41b642051a --- /dev/null +++ b/test/fixtures/basic-types/pages/param.vue @@ -0,0 +1,5 @@ +