Skip to content

Commit

Permalink
fix app router prefetch deduping
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Aug 8, 2024
1 parent 71882db commit 2b6b725
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
7 changes: 5 additions & 2 deletions packages/next/src/client/link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ function prefetch(
}

// We should only dedupe requests when experimental.optimisticClientCache is
// disabled.
if (!options.bypassPrefetchedCheck) {
// disabled & when we're not using the app router. App router handles
// reusing an existing prefetch entry (if it exists) for the same URL.
// If we dedupe in here, we will cause a race where different prefetch kinds
// to the same URL (ie auto vs true) will cause one to be ignored.
if (!options.bypassPrefetchedCheck && !isAppRouter) {
const locale =
// Let the link's locale prop override the default router locale.
typeof options.locale !== 'undefined'
Expand Down
19 changes: 19 additions & 0 deletions test/e2e/app-dir/app-prefetch/app/prefetch-race/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Link from 'next/link'
import React from 'react'

export default function Page() {
return (
<>
<div>
<Link href="/force-dynamic/test-page">
/force-dynamic/test-page (prefetch: auto)
</Link>
</div>
<div>
<Link href="/force-dynamic/test-page" prefetch>
/force-dynamic/test-page (prefetch: true)
</Link>
</div>
</>
)
}
33 changes: 32 additions & 1 deletion test/e2e/app-dir/app-prefetch/prefetching.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { nextTestSetup } from 'e2e-utils'
import { check, waitFor, retry } from 'next-test-utils'
import type { Page, Request } from 'playwright'
import type { Page, Request, Route } from 'playwright'
import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers'

const browserConfigWithFixedTime = {
Expand Down Expand Up @@ -462,5 +462,36 @@ describe('app dir - prefetching', () => {
expect(dashboardRequests[1].priority).toBe('auto') // the second request is the lazy fetch to fill in missing data
})
})

it('should respect multiple prefetch types to the same URL', async () => {
let interceptRequests = false

const browser = await next.browser('/prefetch-race', {
beforePageLoad(page: Page) {
page.route('**/force-dynamic/**', async (route: Route) => {
if (!interceptRequests) {
return route.continue()
}

const request = route.request()
const headers = await request.allHeaders()

if (headers['rsc'] === '1') {
// intentionally stall the request,
// as after the initial page load, there shouldn't be any additional fetches
// since the data should already be available.
} else {
await route.continue()
}
})
},
})

await browser.waitForIdleNetwork()
interceptRequests = true

await browser.elementByCss('[href="/force-dynamic/test-page"]').click()
await browser.waitForElementByCss('#test-page')
})
})
})

0 comments on commit 2b6b725

Please # to comment.