React Server Components, Next.js App Router and examples
May 6, 2023
There were recently a number of discussions in the React community around the state of Server Components, the Next.js App Router and the future of tooling and rendering approaches. Here’s my attempt at a brief summary of concepts and discussions for folks that want highlights.
I also wanted to share (lower down) more “complete” App Router examples I’ve found useful to read through to better understand how everything fits together.
What are React Server Components (RSC)?
- Stateless React components designed to run on the server
- Facilitate a seamless code transition experience, also referred to as “knitting,” between server and client components
- Incorporate data fetching as an integral part of the component tree, allowing for top-level await and server-side data serialization
- RSCs share similarities with Astro components in their server-only mental model
- RSC protocol enables the server to expose a special endpoint for the client to request parts of the component tree, allowing for SPA-like routing with MPA-like architecture
- Adoption of RSCs depends on frameworks implementing the feature
- The React team believes RSCs will eventually be widely adopted and change the ecosystem. React community members open to helping folks adopt RSC.
- Introduce async/await as the primary way to do data fetching from Server Components
- Plan to support client-side data loading with the “use()” hook unwrapping Promises
- React Server Components act as a spec for components working across compatible React frameworks, including Next.js
- Conceptually, Dan likes to think of Server Components as “a skeleton of the app’s data flow and then you layer Client components around them like meat around the skeleton”
How is the Next.js App Router related to Server Components?
- Next.js 13+ introduced the App Router with new features, conventions, and support for React Server Components
- Components in the app directory are React Server Components by default, promoting automatic adoption and improved performance
- React Server Components provide benefits such as leveraging server infrastructure and keeping large dependencies server-side, leading to better performance and reduced client-side bundle size
- Next.js App Router combines server rendering and client-side interactivity, progressively enhancing the application for a seamless user experience
- Client Components can be added to introduce client-side interactivity, similar to the functionality in Next.js 12 and earlier versions
- “use client” directive used to mark components as Client Components
- Components without the “use client” directive automatically rendered as Server Components if not imported by another Client Component
- Server and Client Components can be interleaved in the same component tree, with React handling the merging of both environments
- Next.js users have slowly begun to see performance improvements as a result of adopting RSC and the App directory in production.
What RSC implementations are available (outside of Next.js)?
- Simple implementation from Ben Holmes & Dan Abramov (video)
- Vite + RSC exploration from Fatih Aygun
- Webpack RSC exploration from Hendrik Liebau
- Official demo without a framework (without SSR)
While the above are great reference explorations, Next represents the most complete demo of the intended experience (fully nested routing with data-fetching, SSR, SSG) at the time of writing.
Why a Production Framework (like Next.js or Remix) instead of Create React App?
- Create React App (CRA) offers a limited, client-only development experience, which is too limiting for many modern web applications.
- React can pre-render to HTML, so producing an empty HTML file doesn’t make sense; a more comprehensive approach to rendering should be available.
- CRA should have the ability to statically pre-render component trees, enabling non-empty HTML and continued client-side interactivity.
- Pre-rendering multiple pages requires router integration, which leads to the need for a file-based router solution for most use cases.
- Modern frameworks, such as Next.js and Gatsby, already offer the ability to start 100% static + client, with HTML generation, file-based routing, SPA navigations, and real client code.
- These frameworks also allow developers to easily utilize server-side rendering for dynamic routes, such as reading from a database instead of a file, without rewriting the whole application.
- React Server Components (RSC) can run during the build process, allowing for server-less rendering, as demonstrated in Next.js 13 App Router.
- The shift in focus is not from writing SPAs to not writing SPAs, but rather from being locked into SPAs to using whatever rendering mode makes sense for each page, thus entering the hybrid era.
- This shift is primarily a mental one, where developers start with build-time + client rendering and add server rendering as needed on a per-page basis.
What examples of RSC + Next App Router do you recommend?
- Hacker News (source)
- Movies (source)
- Commerce (source)
- Netflix Clone (TMDB) (source)
- AirBnB Clone (source)
- Drift (source)
- Taxonomy (source)
- Next.js App Playground
Are we moving towards more “hybrid” rendering?
- Combines build-time, server, and client rendering to create a more flexible approach to web development
- Focuses on delivering an optimal result in the end: if a page can be served statically, it will be otherwise a dynamic strategy will be chosen instead (e.g. ISR and/or SSR, CSR + Streaming for subsequent navigations)
- Challenges traditional terminology (SPA, MPA, SSR, SSG) as the landscape of web development converges towards hybrid rendering
- Emphasizes the need for new terminology to better describe modern web development practices
- Represents a mental shift in how developers approach web development, moving from a client-only starting point to a more versatile combination of rendering strategies
- Provides benefits of SPAs (no server needed) while avoiding issues with static rendering (navigation without page reloads)
- React Server Components and Next.js App Router demonstrate the potential of hybrid rendering in action
As the landscape of RSC and App Router begins to settle, we will be aiming to follow along and update our guidance on Server Components over on Patterns.dev. For now, I hope you finds the above notes helpful.
References:
- React.dev new docs: how to start a new project
- New React docs pretend SPAs don’t exist anymore
- Dan Abramov on possible futures for CRA - “client-only doesn’t make sense. way too limiting”
- “petition to retire terms: SPA, MPA, SSR, SSG. they represent the previous generation of tools”
- “most modern React frameworks don’t require a Node.js server anymore. they just let you add one if you need it.”
- Next.js example - purely client-side SPA (no Node.js server, 100% static bundle)
- How to start a React Project in 2023
- Rethinking React best practices
With thanks to Gerald Monaco for reviewing.