Skip to content

dannytlake/next-14-link-prefetch-bug

Repository files navigation

This is a Next.js project bootstrapped with create-next-app.

Prefetching Bug of Dynamic Rendered routes

This repository demonstrates an issue with the next/link component regarding the default behavior of prefetching the Loading UI of links pointing to dynamically rendered routes.

Note: Use Firefox Developer Edition to inspect the prefetched responses for each <Link> visible on the homepage.

The documentation for next/link states the default behavior as "Prefetch behavior depends on whether the route is static or dynamic. For static routes, the full route will be prefetched (including all its data). For dynamic routes, the partial route down to the nearest segment with a loading.js boundary will be prefetched." - See https://nextjs.org/docs/app/api-reference/components/link#prefetch

Impact of issue

This bug negatively affects the user experience by diminishing the perceived performance of navigating to dynamically rendered pages when using the default prefetch behavior. When users click a <Link>, the browser fails to display the loading.js fallback immediately and instead waits for it to be streamed after the navigation request is made. This delay in showing the loading UI can lead to a noticeable performance degradation, especially for users on slower networks or devices.

Although the issue doesn't occur with all routing configurations, it poses a significant challenge for medium to large-scale websites that rely on dynamic rendering and have an app routing configuration beyond the most basic level, ie using route groups, or nested routes with dynamic segments underneath. Additionally, sites that rely on top-level dynamic route segments to support internationalization, ie [locale], are particularly affected as this issue impacts all dynamically rendered pages that rely on the default prefetch behavior.

Failure Cases

The below cases show where the prefetching feature of <Link> fails to correctly fetch the loading.js boundary of each page. The response from the prefetch request to the server does not contain the loading.js fallback.

  • Using a Route Group, ie (example-route-group)/broken
  • Using a route segment, ie example/broken2
  • Using a dynamic segment underneath a route segment, ex /products/[slug]

Example of failed prefetch response that is missing the loading.js fallback:

// from page: (example-route-group)/broken

0:["O4DIzrPgeHEefeF_dZWuy",[["children","(example-route-group)",["(example-route-group)",{"children":["broken-route-group",{"children":["__PAGE__",{}]}]}],null,null]]]

Success Cases

The below cases show where the prefetching feature of <Link> successfully fetches the loading.js boundary of each page.

  • Using a top level dynamig segment, ie /[slug]
  • Using a top level route segment, ie /works

Example of a successful prefetch response that contains the loading.js fallback:

// from page: /3
1:I[5851,[],""]
3:I[841,[],""]
2:["slug","3","d"]
0:["O4DIzrPgeHEefeF_dZWuy",[["children",["slug","3","d"],[["slug","3","d"],{"children":["__PAGE__",{}]}],[["slug","3","d"],{"children":null},[null,["$","$L1",null,{"parallelRouterKey":"children","segmentPath":["children","$2","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],[["$","div",null,{"children":[["$","h2",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}],["$","h3",null,{"children":"Loading..."}]]}],[],[]]],["$L4",null]]]]
4:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"Create Next App"}],["$","meta","3",{"name":"description","content":"Generated by create next app"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]]

How to reproduce

The application must be run in production mode in order for the next/link prefetching to occur.

  • build the application with pnpm build
  • run with pnpm start

See the below responses of each prefetch, taken with Firefox Developer Editon: Prefetch Responses

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published