Skip to content
Journal

Engineering

Next.js 13 and the App Directory: Excited, Not Migrating

Headshot of Alex Fujimoto
Alex Fujimoto
October 27, 2022 · 3 min read

Next.js Conf happened Tuesday, and the headline is Next.js 13: a new app directory built on React Server Components, nested layouts, streaming, plus Turbopack, a Rust bundler with startlingly large speed claims. Our engineering channel has been a wall of links since the keynote. Time to sort the signal from the confetti.

Short version: this is the most important architectural announcement in the React ecosystem in years, and we are not moving client production work to it yet. Both halves of that sentence matter.

What the app directory actually changes

The pages directory model that made Next.js ubiquitous has a coarse grain: data fetching happens per page, layouts are re-rendered by convention and hacks, and every component you write ships JavaScript to the browser whether it needs interactivity or not.

The app directory inverts the defaults. Components are server components unless you opt into the client with a directive. Layouts nest and persist across navigations without re-rendering. Data fetching moves into components with a fetch-based API, and streaming means the shell can render while slow data catches up.

// app/products/layout.tsx renders once, persists across child routes
export default function ProductsLayout({ children }) {
  return (
    <section>
      <FilterSidebar />
      {children}
    </section>
  );
}

The philosophical shift is bigger than the API. For five years the ecosystem has treated the server as a place to pre-render client apps. This treats the client as a place to sprinkle interactivity onto server apps. That is not a new framework feature. That is the pendulum of web architecture visibly swinging, and for content and commerce sites, the kind we build most, the server-first default is honestly the correct one. Less JavaScript shipped for the same experience is a straight win for the Core Web Vitals work we sweat over.

Why we are waiting anyway

The app directory ships in beta, and Vercel deserves credit for labeling it honestly. Our reasons for patience are specific rather than reflexive:

  • The ecosystem has not caught up. CSS-in-JS libraries, data layers, and half the packages in a typical project have not answered the server component question yet. Early adopters will spend real time discovering which dependencies break.
  • Mental model migration is the real cost. The code changes are manageable. Retraining a team's instincts about where state lives and what can be interactive is the actual project, and doing that on a client's dime and deadline is malpractice.
  • Caching semantics need to settle. The new fetch-level caching is powerful and, from the docs so far, subtle. Subtle caching bugs in commerce are revenue bugs.
  • Turbopack is an alpha with a benchmark. Impressive claims, and we have all seen impressive claims. We will let the numbers age a quarter.

Our plan: internal projects and this studio's own site move first, starting next month. That is where we make mistakes on our own budget. Client recommendations follow when the beta label comes off and the ecosystem stabilizes, plausibly mid-2023.

The takeaway for non-engineers

If you are a client reading this: nothing about your current Next.js site is deprecated, the pages directory is explicitly supported for the long haul, and anyone urging you into an emergency migration is selling urgency, not engineering.

But the direction is set, and it is a good direction. The web spent a decade sending more JavaScript to do the browser's job. The next few years will be about sending less. We would rather arrive there deliberately, with the craft intact, than first with the bruises.

Building something this could apply to?

We take on a small number of flagship projects each quarter.

Start a project