Next.js App Directory Architecture First Impressions
Thomas Desmond here, Developer Advocate at Sitecore. Recently I’ve been intrigued by the new Next.js app
directory architecture released in beta with Next.js 13.1. So I set out to build a proof-of-concept app trying out the new architecture in Next.js.
I decided to build a clone of the Vercel Commerce app using Sitecore OrderCloud and the new architecture. I want to give my early impressions of the new architecture and talk about documentation, shifting your mindset to Server Components versus Client Components, package support, and lastly, should you migrate to the new architecture.
Let’s jump in!
1. Documentation
I started my journey into the app directory architecture by reading the documentation. It excited me to see what was possible with the new architecture in Next.js. It was well thought out. And it even uses Vercel’s new page preview feature where visitors can leave comments directly on the page, and you can see your and others’ comments.
This was super helpful because it added clarity to certain sections or you could directly comment about support for different features.
I’d like to add that the documentation is positioned well for someone transitioning from pages-based architecture—lots of comparing old versus new.
To close out documentation, I’d like to add that since this is a very new and BIG change to Next.js. There is not a lot of community documentation…yet (blog posts, videos, tutorials, starter kits). You will likely read GitHub issue threads if you encounter something new or unexpected.
2. Server Components vs. Client Components
One of the biggest changes in the new app directory is that all components are Server Components by default. A server component is a component that renders entirely on the server—leveraging the power of the server to fetch data and reduce dependency requirements for the client.
Ideally, you use Server Components as much as possible to reduce the load on the client. So you want to think with Server Components in mind.
Server Components are great, but they can’t do everything. Specifically, they cannot contain client interactivity. A component built and rendered by the server cannot contain client code. For example, useState
, useEffect
, onClick
all cannot exist inside a Server Component.
Next.js does a great job of showing you an error if these sneak their way into one of your Server Components, but you’ll learn quickly what can and cannot be done in a Server Component.
It’s easy enough to tell a component that it is a Client Component with the new use client
directive that you add to the top of your file. This tells Next.js that this component has client interactivity and needs to be a Client Component. The functionality of a Client Component is that it is pre-rendered on the server and then hydrated on the client.
1'use client' 2import { useState } from 'react'; 3 4export default function Counter() { 5 const [active, setActive] = useState(false); 6 7 return ( 8 <> 9 // Your code here 10 </> 11 ); 12}
At first, I thought putting use client
in many of my files indicated I was doing something wrong. But in the previous pages
architecture, everything was a Client Component. So it may just be that I am a little used to the old architecture and not fully thinking with my Server Component hat yet.
But some of the packages and libraries I like to use in Next.js require using Client Components, which was a big reason for me having the use client
in many files.
So that leads me to Package Support
3. Package Support
A new architecture is a serious change. This is a breaking change for some packages and libraries.
An early difficulty I encountered was using UI component libraries like Mantine and Material UI in the new architecture. After looking through some GitHub issues, the culprit is Emotion, a package many component libraries rely on that does not support server rendering.
With a custom initialization setup, I did get Mantine working for my Client Components. But that meant any component with UI was going to be Client Components, not taking advantage of those Server Component benefits.
It’s unclear if Emotion will or can ever support being Server Rendered, but they are aware of the problem and have issues open tracking how they want to move forward.
Mantine with Next.js 13 app dir Issue #2815
Emotion: Plans to support Next.js 13 - /app directory Issue #2928
This was the only major package support hurdle I had to take on, but it did take custom code, and even the Mantine team says it’s not fully tested or supported in its current state.
Bringing in simpler packages that didn’t require setup or initialization worked out of the box, so most of your packages and libraries should be supported. However, it’s worth checking with the developers or maintainers to see if the new app directory is supported.
It’s worth noting that currently, the recommended UI styling choice for the app directory is to use CSS or tools that generate CSS like Tailwind. Component libraries like Mantine and Material UI do not take full advantage of new app
directory features.
4. Migrate now or later?
Finally, we are at the question. Should you migrate to the new architecture?
The short answer is no.
At the time the app directory architecture is still in beta and not recommended for production.
But if you are a Next.js user and plan to continue using Next.js, I think it’s a good idea to start poking around and experimenting with the new architecture. Maybe build a small side project with it to get a feel for it.
Or the page architecture and app architecture can work together. It’s not one or the other. So you could consider building out your next feature in the app directory. Keep all your existing app functionality in the pages directory but get a feel for the app directory changes by building a new feature.
Overall I like the new architecture. It looks like it will allow for more options when building your pages and components to mix and match static versus dynamic content. It’s a big change for Next.js but a step forward in allowing you to do more.