From 82f4fd3e8c792c8c2f304091c0c6c9aa90cd9cad Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 27 Feb 2023 17:07:26 -0800 Subject: [PATCH] Update router filter to be less sensitive (#46515) This skips including dynamic redirects in the client router filter as it causes extra unexpected hard navigations. x-ref: [slack thread](https://vercel.slack.com/archives/C04MEB9L9RQ/p1677521159911179?thread_ts=1677255545.574209&cid=C04MEB9L9RQ) ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md) --- packages/next/src/build/index.ts | 2 +- ...lter.ts => create-client-router-filter.ts} | 26 ++++++------------- .../next/src/server/dev/next-dev-server.ts | 2 +- packages/next/src/shared/lib/router/router.ts | 2 +- test/e2e/app-dir/app/index.test.ts | 2 -- test/e2e/app-dir/app/next.config.js | 4 +-- 6 files changed, 13 insertions(+), 25 deletions(-) rename packages/next/src/lib/{create-router-client-filter.ts => create-client-router-filter.ts} (74%) diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 608d83211e424..b555e26788846 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -132,7 +132,7 @@ import { webpackBuild } from './webpack-build' import { NextBuildContext } from './build-context' import { normalizePathSep } from '../shared/lib/page-path/normalize-path-sep' import { isAppRouteRoute } from '../lib/is-app-route-route' -import { createClientRouterFilter } from '../lib/create-router-client-filter' +import { createClientRouterFilter } from '../lib/create-client-router-filter' export type SsgRoute = { initialRevalidateSeconds: number | false diff --git a/packages/next/src/lib/create-router-client-filter.ts b/packages/next/src/lib/create-client-router-filter.ts similarity index 74% rename from packages/next/src/lib/create-router-client-filter.ts rename to packages/next/src/lib/create-client-router-filter.ts index 40f4ebfbe19d4..715e232943484 100644 --- a/packages/next/src/lib/create-router-client-filter.ts +++ b/packages/next/src/lib/create-client-router-filter.ts @@ -1,7 +1,9 @@ +import { Token } from 'next/dist/compiled/path-to-regexp' import { BloomFilter } from '../shared/lib/bloom-filter' import { isDynamicRoute } from '../shared/lib/router/utils' import { removeTrailingSlash } from '../shared/lib/router/utils/remove-trailing-slash' import { Redirect } from './load-custom-routes' +import { tryToParsePath } from './try-to-parse-path' const POTENTIAL_ERROR_RATE = 0.02 @@ -42,26 +44,14 @@ export function createClientRouterFilter( for (const redirect of redirects) { const { source } = redirect const path = removeTrailingSlash(source) + let tokens: Token[] = [] - if (path.includes(':') || path.includes('(')) { - let subPath = '' - const pathParts = path.split('/') - - for (let i = 1; i < pathParts.length + 1; i++) { - const curPart = pathParts[i] - - if (curPart.includes(':') || curPart.includes('(')) { - break - } - subPath = `${subPath}/${curPart}` - } + try { + tokens = tryToParsePath(source).tokens || [] + } catch (_) {} - // if redirect has matcher at top-level we don't include this - // as it would match everything - if (subPath) { - dynamicPaths.add(subPath) - } - } else { + if (tokens.every((token) => typeof token === 'string')) { + // only include static redirects initially staticPaths.add(path) } } diff --git a/packages/next/src/server/dev/next-dev-server.ts b/packages/next/src/server/dev/next-dev-server.ts index d17dddcba32cb..38da04275efad 100644 --- a/packages/next/src/server/dev/next-dev-server.ts +++ b/packages/next/src/server/dev/next-dev-server.ts @@ -96,7 +96,7 @@ import { CachedFileReader } from '../future/route-matcher-providers/dev/helpers/ import { DefaultFileReader } from '../future/route-matcher-providers/dev/helpers/file-reader/default-file-reader' import { NextBuildContext } from '../../build/build-context' import { logAppDirError } from './log-app-dir-error' -import { createClientRouterFilter } from '../../lib/create-router-client-filter' +import { createClientRouterFilter } from '../../lib/create-client-router-filter' // Load ReactDevOverlay only when needed let ReactDevOverlayImpl: FunctionComponent diff --git a/packages/next/src/shared/lib/router/router.ts b/packages/next/src/shared/lib/router/router.ts index a0724f98039b6..0ef009460683e 100644 --- a/packages/next/src/shared/lib/router/router.ts +++ b/packages/next/src/shared/lib/router/router.ts @@ -1063,7 +1063,7 @@ export default class Router implements BaseRouter { new URL(curAs, 'http://n').pathname ) const asNoSlashLocale = addBasePath( - addLocale(curAs, locale || this.locale) + addLocale(asNoSlash, locale || this.locale) ) if ( diff --git a/test/e2e/app-dir/app/index.test.ts b/test/e2e/app-dir/app/index.test.ts index 2ede44cf0681e..48ae6772fb8cb 100644 --- a/test/e2e/app-dir/app/index.test.ts +++ b/test/e2e/app-dir/app/index.test.ts @@ -20,10 +20,8 @@ createNextDescribe( { pathname: '/redirect-1' }, { pathname: '/redirect-2' }, { pathname: '/blog/old-post' }, - { pathname: '/redirect-3/some/value' }, { pathname: '/redirect-3/some' }, { pathname: '/redirect-4' }, - { pathname: '/redirect-4/another' }, ])( 'should match redirects in pages correctly $path', async ({ pathname }) => { diff --git a/test/e2e/app-dir/app/next.config.js b/test/e2e/app-dir/app/next.config.js index 2ba7f85013c28..59ae738ab2dae 100644 --- a/test/e2e/app-dir/app/next.config.js +++ b/test/e2e/app-dir/app/next.config.js @@ -45,12 +45,12 @@ module.exports = { permanent: false, }, { - source: '/redirect-3/some/:path*', + source: '/redirect-3/some', destination: 'https://example.vercel.sh', permanent: false, }, { - source: '/redirect-4/:path*', + source: '/redirect-4', destination: 'https://example.vercel.sh', permanent: false, },