Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions docs/01-app/02-guides/instant-navigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -84,29 +84,28 @@ Validation runs automatically on every page load using the real request from you

The Next.js DevTools let you see what users see on page loads and client navigations before dynamic data streams in. Use it to verify your loading states look right, check that the right content appears immediately, and iterate on where to place `<Suspense>` boundaries.

Enable the toggle in your Next.js config:
The Navigation Inspector is available when Cache Components is enabled:

```ts filename="next.config.ts" highlight={5-7}
```ts filename="next.config.ts" highlight={4}
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
cacheComponents: true,
experimental: {
instantNavigationDevToolsToggle: true,
},
}

export default nextConfig
```

Open the Next.js DevTools and select **Instant Navs**. Two options are available:
Open the Next.js DevTools and select **Navigation Inspector**, then click **Start Capturing**. While capturing is active:

- **Page load**: click **Reload** to refresh the page and freeze it at the initial static UI generated for this route, before any dynamic data streams in.
- **Client navigation**: once enabled, clicking any link in your app shows the prefetched UI for that page instead of the full result.
- Refresh the page to freeze the initial static UI generated for the route, before any dynamic data streams in.
- Click a link to freeze the prefetched UI for the destination route.

Try a **page load** on the product page. Two separate fallbacks appear: "Loading product..." and "Checking availability...". On the first visit the cache is cold and both fallbacks are visible. Navigate to the page again and the product name appears immediately from cache.
When the UI is frozen, click **Continue Rendering** to let the current navigation finish while keeping the Navigation Inspector in capturing mode. Click **Stop Capturing** when you are done inspecting loading states.

Now try a **client navigation** (click a link from `/store/shoes` to `/store/hats`). The product name and price appear immediately (cached). "Checking availability..." shows where inventory will stream in.
Try refreshing the product page. Two separate fallbacks appear: "Loading product..." and "Checking availability...". On the first visit the cache is cold and both fallbacks are visible. Navigate to the page again and the product name appears immediately from cache.

Now click a link from `/store/shoes` to `/store/hats`. The product name and price appear immediately (cached). "Checking availability..." shows where inventory will stream in.

> **Good to know:** Page loads and client navigations can produce different shells. Client-side hooks like `useSearchParams` suspend on page loads (search params are not known at build time) but resolve synchronously on client navigations (the router already has the params).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,22 +122,20 @@ Setting `unstable_instant = false` on a segment opts it out of validation entire

## Inspecting loading states

Enable the DevTools toggle with the experimental flag:
The Navigation Inspector is available when Cache Components is enabled:

```js filename="next.config.js"
module.exports = {
experimental: {
instantNavigationDevToolsToggle: true,
},
cacheComponents: true,
}
```

Open the Next.js DevTools and select **Instant Navs**. Two options are available:
Open the Next.js DevTools and select **Navigation Inspector**, then click **Start Capturing**. While capturing is active:

- **Page load**: click **Reload** to refresh the page and freeze it at the initial static UI that was generated for this route, before any dynamic data streams in.
- **Client navigation**: once enabled, clicking any link in your app shows the prefetched UI for that page instead of the full result.
- Refresh the page to freeze the initial static UI generated for the route, before any dynamic data streams in.
- Click a link to freeze the prefetched UI for the destination route.

Use both to check that your loading states look right on first visit and on navigation.
When the UI is frozen, click **Continue Rendering** to let the current navigation finish while keeping the Navigation Inspector in capturing mode. Click **Stop Capturing** when you are done. Use both page refreshes and link clicks to check that your loading states look right on first visit and on navigation.

## Testing instant navigation

Expand All @@ -151,7 +149,7 @@ import { instant } from '@next/playwright'

## Known issue: shared cookie across projects

The DevTools use a `next-instant-navigation-testing` cookie to hold back dynamic content and freeze the page at the instant UI. Because cookies are scoped to the domain and not the port, running multiple projects on the same domain (typically `localhost`) means the cookie is shared across them and can cause unexpected behavior. Clear the cookie or close the Instant Navs panel when switching between projects to avoid issues.
The DevTools use a `next-instant-navigation-testing` cookie to hold back dynamic content and freeze the page at the instant UI. Because cookies are scoped to the domain and not the port, running multiple projects on the same domain (typically `localhost`) means the cookie is shared across them and can cause unexpected behavior. Clear the cookie or close the Navigation Inspector panel when switching between projects to avoid issues.

> **Good to know:** This will be fixed as part of stabilizing the feature.

Expand Down
3 changes: 1 addition & 2 deletions packages/next/src/build/define-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ export function getDefineEnv({
'process.env.__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS': Boolean(
config.experimental.cachedNavigations
),
'process.env.__NEXT_INSTANT_NAV_TOGGLE':
!!config.experimental.instantNavigationDevToolsToggle,
'process.env.__NEXT_INSTANT_NAV_TOGGLE': isCacheComponentsEnabled,
'process.env.__NEXT_USE_CACHE': isUseCacheEnabled,
'process.env.__NEXT_USE_NODE_STREAMS': isEdgeServer
? false
Expand Down
1 change: 0 additions & 1 deletion packages/next/src/server/config-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ export const experimentalSchema = {
externalMiddlewareRewritesResolve: z.boolean().optional(),
externalProxyRewritesResolve: z.boolean().optional(),
exposeTestingApiInProductionBuild: z.boolean().optional(),
instantNavigationDevToolsToggle: z.boolean().optional(),
fallbackNodePolyfills: z.literal(false).optional(),
fetchCacheKeyPrefix: z.string().optional(),
forceSwcTransforms: z.boolean().optional(),
Expand Down
6 changes: 0 additions & 6 deletions packages/next/src/server/config-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,6 @@ export interface ExperimentalConfig {
* Do not enable in user-facing production deployments.
*/
exposeTestingApiInProductionBuild?: boolean
/**
* Show the Instant Navigation Mode toggle in the dev tools indicator.
* When enabled, a menu item lets you lock navigations to only show
* the cached/prefetched state.
*/
instantNavigationDevToolsToggle?: boolean
extensionAlias?: Record<string, any>
allowedRevalidateHeaderKeys?: string[]
fetchCacheKeyPrefix?: string
Expand Down
3 changes: 0 additions & 3 deletions test/development/app-dir/instant-navs-devtools/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
*/
const nextConfig = {
cacheComponents: true,
experimental: {
instantNavigationDevToolsToggle: true,
},
}

module.exports = nextConfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const nextConfig = {
experimental: {
// Enable the testing API in production builds for these tests
exposeTestingApiInProductionBuild: true,
instantNavigationDevToolsToggle: true,
prefetchInlining: false,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const nextConfig = {
cacheComponents: true,
experimental: {
exposeTestingApiInProductionBuild: true,
instantNavigationDevToolsToggle: true,
prefetchInlining: false,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const nextConfig: NextConfig = {
cachedNavigations: true,
prefetchInlining: false,
exposeTestingApiInProductionBuild: true,
instantNavigationDevToolsToggle: true,
optimisticRouting: true,
useOffline: true,
varyParams: true,
Expand Down
Loading