A navigation that is instant today goes slow the day someone adds a cookies() read to a shared header or moves a <Suspense> boundary. No suite above notices: the page renders the same text, just later. Next.js 16.3 10,514 offers two guards, the cheaper one in the build. With cacheComponents: true (Enabling Cache Components), deleting the boundary fails next build:
$ npx next build
Error: Route "/products": Next.js encountered uncached or runtime data during prerendering.
`fetch(...)`, `cookies()`, `headers()`, `params`, `searchParams`, or `connection()` accessed
outside of `<Suspense>` prevents the route from being prerendered, blocking the page load.
Ways to fix this:
- [stream] Provide a placeholder with `<Suspense fallback={...}>` around the data access
- [cache] For uncached data (`fetch`, database calls): cache the access with `"use cache"`
- [block] Set `export const instant = false` to allow a blocking routeRestore the boundary and the route reports as ◐ (Partial Prerender). That check is free, so run next build in CI ahead of the suites.
What the build cannot judge is which content belongs in the shell. @next/playwright 16.3.5 adds an instant() helper for that: inside its callback, navigations render only cached and prefetched content, and dynamic data is held back until the callback returns, so assertions are not a race.
import { instant } from '@next/playwright';
test('the products shell appears without waiting for data', async ({ page }) => {
await page.goto('/');
await instant(page, async () => {
await page.getByRole('link', { name: 'Products' }).click();
await expect(page.getByRole('heading', { name: 'Products' })).toBeVisible();
await expect(page.getByTestId('loading')).toBeVisible();
});
await expect(page.getByText('Enamel mug — $12.00')).toBeVisible();
});The heading and the placeholder must be instant, the product name only after the callback. Move the boundary up so it wraps the whole page: the build still succeeds, the spec of Playwright still passes, and this one does not.
x 2 [chromium] › e2e\instant.spec.ts:4:5 › the products shell appears ... (6.2s)
Error: expect(locator).toBeVisible() failed
Locator: getByTestId('loading')
Error: element(s) not found