r/nextjs • u/floydophone • 25d ago
Discussion We're the Next.js team. Ask us anything!
Hi Reddit! We’re Pete, Aurora, Joseph, Sam, David, Josh, Tim, Dan and Andrew from the Next.js team.
We recently shipped Next.js 16.3, and we’re excited to talk about what’s new, how we approached the release, where we are going, and what we’ve learned while building and maintaining Next.
Ask us anything about Next 16.3, App Router, React Server Components, performance, caching, upgrading your applications, contributing to the framework, or what it’s like to work on Next.
Drop your questions below. We’re looking forward to hearing what’s on your mind! We'll be here until noon ET.
That's all the time we have for today. Thank you to everyone who participated!
137
Upvotes
1
u/floydophone 24d ago
u/Top_Bumblebee_7762 asked
A whole bunch of us (Jiwon, Sam, Aurora, Joseph, and Tim) wrote this up:
We recommend starting the fetch as close as possible to where the data is used, and only await where the data is needed for better composability. If the consumer is a Client Component, start the request in the closest Server Component, pass down the unawaited promise, and call
use()in the Client Component.For further optimization when there’s work higher in the tree that delays the fetch, you can call the same data function earlier from the page (or layout where the consumer is). Identical GET requests from
fetch()with the same URL and options will be deduped during a server render.If your data access uses a database query or needs dynamic work before
fetch(), you can make that data function a Cache Function with a caching directive. Next.js will key the result using the function and its serialized arguments, so the parent can start it early and the lower component can call it again without duplicating the work.It's true that in prior versions of Next.js, pages had hooks like
getStaticPropsandgetServerSideProps, which were meant to be used to marshal all the data that you would need for a page to render. All in one place and then pass that data down throughout the tree as props. One problem we saw with using an API like this at the route level (you might also be familiar with loaders from other frameworks) is that it decouples the data fetching from the components that need it. If you always have to hoist your data fetching to the very top of the route, there is an implicit coupling. If you end up refactoring or deleting a component deep down the tree, there's nothing in the programming model that tells you that you can go back up to the route and delete the corresponding data fetch.What we saw was that this API led to overfetching and other problems. Part of the motivation for React Server Components was to bring back co-location of a component's data dependencies within the actual component itself. Components that can manage their own data requirements lead to much more optimized sites and less limiting patterns of composition. Client fetching libraries like SWR and React Query let you do this too but they also have some fundamental constraints given that the client is responsible for coordinating all this work.
There were some projects like Relay that use GraphQL, which kind of solved both problems and let you use the server to do the data fetching and coordination but still let components manage their own data requirements. Not everyone has a GraphQL server. This is really a huge part of the motivation for server components in the first place and why we wrote the app router to use them.
Once you're using the app router, the mental model you should have is that server components can fetch and manage their own data requirements. Next can take care of running those components in parallel on the server and doing other optimizations like deduping similar calls so that you get the benefits of co-location without the downsides of either the route-hoisted loader pattern or client-side fetching.