mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
46681d90f0
This PR makes Sync IO behavior more restrictive when `partialPrefetching` is on (either globally or for a page). - Previously, we allowed `await cookies(); Date.now()` in in segments that won't ever be runtime prefetched. This was achieved by separating segments into "early" and "late" stages and only erroring in the "early" ones. - After this PR, it will always be an error to do sync IO anywhere other than after `io()`/`connection()`/uncached IO (i.e. outside the Dynamic stage). We're doing this mainly because with `partialPrefetching`, `cookies()` resolves in App Shells, and sync IO causes a severe deopt in any prerender. `allow-runtime` also opts a route into `partialPrefetching`, which means that even the segments above the runtime prefetch boundary will need an App Shell and can't tolerate Sync IO. This PR removes all early/late stage separation, because we no longer need to vary the Sync IO behavior on the segment. Instead, we now pick whether a stageController should use - `SyncIOMode.AllowedInRuntimeOrDynamic` (legacy) - `SyncIOMode.AllowedInDynamic` (`partialPrefetching`) - `SyncIOMode.Untracked` if it needs to opt out I've removed the existing tests that asserted that sync IO is allowed in segments above the `allow-runtime` boundary. Instead, we check that sync io either errors (if partialPrefetching is on) or is allowed (if partialPrefetching is off) Closes NAR-855
133 lines
3.9 KiB
TypeScript
133 lines
3.9 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
|
|
describe('react-performance-track', () => {
|
|
// false is the default when visiting pages as an ordinary user.
|
|
// true is the default when having Chrome DevTools open.
|
|
// Hardcoded for now since most of the actual behavior is not intended.
|
|
const disableCache = false
|
|
const extraHTTPHeaders = disableCache
|
|
? { 'Cache-Control': 'no-cache' }
|
|
: undefined
|
|
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
it('should show setTimeout', async () => {
|
|
const browser = await next.browser('/set-timeout', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{ name: '\u200bsetTimeout', properties: [] },
|
|
{ name: '\u200bsetTimeout', properties: [] },
|
|
])
|
|
)
|
|
})
|
|
|
|
it('should show fetch', async () => {
|
|
const browser = await next.browser('/fetch', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
// React might decide to display the shorthand in round brackets differently.
|
|
// Double check with React changes if a shorthand change is intended.
|
|
name: '\u200bfetch (…/random)',
|
|
properties: expect.arrayContaining([
|
|
['status', '200'],
|
|
['url', '"https://next-data-api-endpoint.vercel.app/api/random"'],
|
|
]),
|
|
},
|
|
])
|
|
)
|
|
})
|
|
|
|
it('should show params', async () => {
|
|
const browser = await next.browser('/params/next', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
name: '\u200bparams [Prefetch]',
|
|
properties: [],
|
|
},
|
|
])
|
|
)
|
|
})
|
|
|
|
it('should show searchParams', async () => {
|
|
const browser = await next.browser('/searchparams?slug=next', {
|
|
extraHTTPHeaders,
|
|
})
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
name: '\u200bsearchParams [Prefetch]',
|
|
properties: [],
|
|
},
|
|
])
|
|
)
|
|
})
|
|
|
|
it('should show cookies', async () => {
|
|
const browser = await next.browser('/cookies', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
name: '\u200bcookies [Prefetch]',
|
|
properties: [],
|
|
},
|
|
])
|
|
)
|
|
})
|
|
|
|
it('should show draftMode', async () => {
|
|
const browser = await next.browser('/draftMode', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual([])
|
|
})
|
|
|
|
it('should show headers', async () => {
|
|
const browser = await next.browser('/headers', { extraHTTPHeaders })
|
|
await browser.elementByCss('[data-react-server-requests-done]', {
|
|
state: 'attached',
|
|
})
|
|
|
|
const track = await browser.eval('window.reactServerRequests.getSnapshot()')
|
|
expect(track).toEqual(
|
|
expect.arrayContaining([
|
|
{
|
|
name: '\u200bheaders [Prefetch]',
|
|
properties: [],
|
|
},
|
|
])
|
|
)
|
|
})
|
|
})
|