Skip to content

Commit b304b45

Browse files
authored
bugfix (pages): assetPrefix should not cause hard nav in development (#79176)
In development when handling the page request, we are sending the parsedUrl with the basePath stripped but not assetPrefix. As a result, when setting an assetPrefix, the chunk would 404 which causes a hard nav. It'd then recover and work correctly on subsequent navs. This applies the exact same handling we had for basePath, but for assetPrefix. Fixes #77241
1 parent 7ddd5ef commit b304b45

File tree

6 files changed

+50
-5
lines changed

6 files changed

+50
-5
lines changed

packages/next/src/server/lib/router-server.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,11 +327,20 @@ export async function initialize(opts: {
327327
if (blockCrossSite(req, res, config.allowedDevOrigins, opts.hostname)) {
328328
return
329329
}
330+
330331
const origUrl = req.url || '/'
331332

333+
// both the basePath and assetPrefix need to be stripped from the URL
334+
// so that the development bundler can find the correct file
332335
if (config.basePath && pathHasPrefix(origUrl, config.basePath)) {
333336
req.url = removePathPrefix(origUrl, config.basePath)
337+
} else if (
338+
config.assetPrefix &&
339+
pathHasPrefix(origUrl, config.assetPrefix)
340+
) {
341+
req.url = removePathPrefix(origUrl, config.assetPrefix)
334342
}
343+
335344
const parsedUrl = url.parse(req.url || '/')
336345

337346
const hotReloaderResult = await developmentBundler.hotReloader.run(
@@ -343,6 +352,7 @@ export async function initialize(opts: {
343352
if (hotReloaderResult.finished) {
344353
return hotReloaderResult
345354
}
355+
346356
req.url = origUrl
347357
}
348358

@@ -370,6 +380,11 @@ export async function initialize(opts: {
370380

371381
if (config.basePath && pathHasPrefix(origUrl, config.basePath)) {
372382
req.url = removePathPrefix(origUrl, config.basePath)
383+
} else if (
384+
config.assetPrefix &&
385+
pathHasPrefix(origUrl, config.assetPrefix)
386+
) {
387+
req.url = removePathPrefix(origUrl, config.assetPrefix)
373388
}
374389

375390
if (resHeaders) {

packages/next/src/server/lib/router-utils/resolve-routes.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,19 @@ export function getResolveRoutes(
189189
parsedUrl.pathname || '',
190190
config.basePath
191191
)
192+
let normalizedPath = parsedUrl.pathname || '/'
193+
194+
if (config.basePath && pathHasPrefix(normalizedPath, config.basePath)) {
195+
normalizedPath = removePathPrefix(normalizedPath, config.basePath)
196+
} else if (
197+
config.assetPrefix &&
198+
pathHasPrefix(normalizedPath, config.assetPrefix)
199+
) {
200+
normalizedPath = removePathPrefix(normalizedPath, config.assetPrefix)
201+
}
202+
192203
initialLocaleResult = normalizeLocalePath(
193-
removePathPrefix(parsedUrl.pathname || '/', config.basePath),
204+
normalizedPath,
194205
config.i18n.locales
195206
)
196207

test/development/basic/asset-prefix/asset-prefix.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { join } from 'path'
22
import { nextTestSetup } from 'e2e-utils'
3-
import { check } from 'next-test-utils'
3+
import { check, retry } from 'next-test-utils'
44

55
describe('asset-prefix', () => {
66
const { next } = nextTestSetup({
@@ -11,7 +11,7 @@ describe('asset-prefix', () => {
1111
const browser = await next.browser('/')
1212
await browser.eval(`window.__v = 1`)
1313

14-
expect(await browser.elementByCss('div').text()).toBe('Hello World')
14+
expect(await browser.elementByCss('#text').text()).toBe('Hello World')
1515

1616
await check(async () => {
1717
const logs = await browser.log()
@@ -24,6 +24,16 @@ describe('asset-prefix', () => {
2424
expect(await browser.eval(`window.__v`)).toBe(1)
2525
})
2626

27+
it('should navigate to another page without hard navigating', async () => {
28+
const browser = await next.browser('/')
29+
await browser.eval(`window.__v = 1`)
30+
await browser.elementByCss('[href="/page2"]').click()
31+
await retry(async () => {
32+
expect(await browser.elementByCss('div').text()).toBe('Page 2')
33+
})
34+
expect(await browser.eval(`window.__v`)).toBe(1)
35+
})
36+
2737
describe('rewrites', () => {
2838
it('rewrites that do not start with assetPrefix should still work', async () => {
2939
const res = await next.fetch('/not-custom-asset-prefix/api/test-json', {})

test/development/basic/asset-prefix/fixture/next.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const ASSET_PREFIX = 'custom-asset-prefix'
1+
const ASSET_PREFIX = '/custom-asset-prefix'
22

33
module.exports = {
44
assetPrefix: ASSET_PREFIX,
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import Link from 'next/link'
12
import React from 'react'
23

34
export default function Page() {
4-
return <div>Hello World</div>
5+
return (
6+
<>
7+
<div id="text">Hello World</div>
8+
<Link href="/page2">Page 2</Link>
9+
</>
10+
)
511
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default function Page2() {
2+
return <div>Page 2</div>
3+
}

0 commit comments

Comments
 (0)