未验证 提交 dcdcf49a 编写于 作者: J JJ Kasper 提交者: GitHub

Fix resolving href with a rewrite (#16975)

This makes sure we properly resolve a rewrite when only the `href` value is used. This was causing a full-reload and was missed in the existing test since we weren't making sure a full navigation didn't occur which has been added in this PR. 

Fixes: https://github.com/vercel/next.js/issues/16974
上级 72b78f3b
......@@ -609,7 +609,7 @@ export default class Router implements BaseRouter {
method = 'replaceState'
}
const route = removePathTrailingSlash(pathname)
let route = removePathTrailingSlash(pathname)
const { shallow = false } = options
// we need to resolve the as value using rewrites for dynamic SSG
......@@ -625,6 +625,25 @@ export default class Router implements BaseRouter {
query,
(p: string) => this._resolveHref({ pathname: p }, pages).pathname!
)
if (resolvedAs !== as) {
const potentialHref = removePathTrailingSlash(
this._resolveHref(
Object.assign({}, parsed, { pathname: resolvedAs }),
pages,
false
).pathname!
)
// if this directly matches a page we need to update the href to
// allow the correct page chunk to be loaded
if (pages.includes(potentialHref)) {
route = potentialHref
pathname = potentialHref
parsed.pathname = pathname
url = formatWithValidation(parsed)
}
}
}
resolvedAs = delBasePath(resolvedAs)
......@@ -980,10 +999,10 @@ export default class Router implements BaseRouter {
return this.asPath !== asPath
}
_resolveHref(parsedHref: UrlObject, pages: string[]) {
_resolveHref(parsedHref: UrlObject, pages: string[], applyBasePath = true) {
const { pathname } = parsedHref
const cleanPathname = removePathTrailingSlash(
denormalizePagePath(delBasePath(pathname!))
denormalizePagePath(applyBasePath ? delBasePath(pathname!) : pathname!)
)
if (cleanPathname === '/404' || cleanPathname === '/_error') {
......@@ -998,7 +1017,7 @@ export default class Router implements BaseRouter {
isDynamicRoute(page) &&
getRouteRegex(page).re.test(cleanPathname!)
) {
parsedHref.pathname = addBasePath(page)
parsedHref.pathname = applyBasePath ? addBasePath(page) : page
return true
}
})
......
......@@ -2,6 +2,7 @@ import { ParsedUrlQuery } from 'querystring'
import pathMatch from './path-match'
import prepareDestination from './prepare-destination'
import { Rewrite } from '../../../../lib/load-custom-routes'
import { removePathTrailingSlash } from '../../../../client/normalize-trailing-slash'
const customRouteMatcher = pathMatch(true)
......@@ -33,7 +34,7 @@ export default function resolveRewrites(
asPath = destRes.parsedDestination.pathname!
Object.assign(query, destRes.parsedDestination.query)
if (pages.includes(asPath)) {
if (pages.includes(removePathTrailingSlash(asPath))) {
// check if we now match a page as this means we are done
// resolving the rewrites
break
......
import { useRouter } from 'next/router'
export default function Page() {
return `auto-export ${useRouter().query.slug}`
return <p id="auto-export">auto-export {useRouter().query.slug}</p>
}
......@@ -28,5 +28,9 @@ export default () => (
<a id="to-params">to params</a>
</Link>
<br />
<Link href="/rewriting-to-auto-export">
<a id="to-rewritten-dynamic">to rewritten dynamic</a>
</Link>
<br />
</>
)
......@@ -316,11 +316,13 @@ const runTests = (isDev = false) => {
it('should work with rewrite when manually specifying href/as', async () => {
const browser = await webdriver(appPort, '/nav')
await browser.eval('window.beforeNav = 1')
await browser
.elementByCss('#to-params-manual')
.click()
.waitForElementByCss('#query')
expect(await browser.eval('window.beforeNav')).toBe(1)
const query = JSON.parse(await browser.elementByCss('#query').text())
expect(query).toEqual({
something: '1',
......@@ -330,11 +332,13 @@ const runTests = (isDev = false) => {
it('should work with rewrite when only specifying href', async () => {
const browser = await webdriver(appPort, '/nav')
await browser.eval('window.beforeNav = 1')
await browser
.elementByCss('#to-params')
.click()
.waitForElementByCss('#query')
expect(await browser.eval('window.beforeNav')).toBe(1)
const query = JSON.parse(await browser.elementByCss('#query').text())
expect(query).toEqual({
something: '1',
......@@ -342,6 +346,20 @@ const runTests = (isDev = false) => {
})
})
it('should work with rewrite when only specifying href and ends in dynamic route', async () => {
const browser = await webdriver(appPort, '/nav')
await browser.eval('window.beforeNav = 1')
await browser
.elementByCss('#to-rewritten-dynamic')
.click()
.waitForElementByCss('#auto-export')
expect(await browser.eval('window.beforeNav')).toBe(1)
const text = await browser.eval(() => document.documentElement.innerHTML)
expect(text).toContain('auto-export hello')
})
it('should match a page after a rewrite', async () => {
const html = await renderViaHTTP(appPort, '/to-hello')
expect(html).toContain('Hello')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册