diff --git a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
index 3876c9356b35d..1c568b61fd6c3 100644
--- a/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
+++ b/packages/next/src/server/app-render/walk-tree-with-flight-router-state.tsx
@@ -108,14 +108,16 @@ export async function walkTreeWithFlightRouterState({
// Explicit refresh
flightRouterState[3] === 'refetch'
+ // Pre-PPR, the `loading` component signals to the router how deep to render the component tree
+ // to ensure prefetches are quick and inexpensive. If there's no `loading` component anywhere in the tree being rendered,
+ // the prefetch will be short-circuited to avoid requesting a potentially very expensive subtree. If there's a `loading`
+ // somewhere in the tree, we'll recursively render the component tree up until we encounter that loading component, and then stop.
const shouldSkipComponentTree =
// loading.tsx has no effect on prefetching when PPR is enabled
!experimental.ppr &&
isPrefetch &&
!Boolean(components.loading) &&
- (flightRouterState ||
- // If there is no flightRouterState, we need to check the entire loader tree, as otherwise we'll be only checking the root
- !hasLoadingComponentInTree(loaderTree))
+ !hasLoadingComponentInTree(loaderTree)
if (!parentRendered && renderComponentsOnThisLevel) {
const overriddenSegment =
diff --git a/test/e2e/app-dir/app-prefetch/app/page.js b/test/e2e/app-dir/app-prefetch/app/page.js
index 17c9aeae53c0b..ccded0f324b50 100644
--- a/test/e2e/app-dir/app-prefetch/app/page.js
+++ b/test/e2e/app-dir/app-prefetch/app/page.js
@@ -8,6 +8,9 @@ export default function HomePage() {
To Static Page
+
+ To Dynamic Slug Page
+
>
)
}
diff --git a/test/e2e/app-dir/app-prefetch/app/prefetch-auto/[slug]/layout.js b/test/e2e/app-dir/app-prefetch/app/prefetch-auto/[slug]/layout.js
index a9123d41fc185..f404ca3e0a91f 100644
--- a/test/e2e/app-dir/app-prefetch/app/prefetch-auto/[slug]/layout.js
+++ b/test/e2e/app-dir/app-prefetch/app/prefetch-auto/[slug]/layout.js
@@ -2,7 +2,18 @@ import Link from 'next/link'
export const dynamic = 'force-dynamic'
+function getData() {
+ const res = new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({ message: 'Layout Data!' })
+ }, 2000)
+ })
+ return res
+}
+
export default async function Layout({ children }) {
+ const result = await getData()
+
return (
Layout
@@ -10,6 +21,7 @@ export default async function Layout({ children }) {
Prefetch Link
{children}
+