Writing
First Impressions: Next.js 13

By Thomas Wang / @thomaswang
Updated on November 6, 2022

Next.js has always been a hybrid web framework, augmenting React’s powerful client-side features with sane file conventions and crucial server-side functionality via getServerSideProps, incremental static regeneration, and api routes.

With the introduction of the app directory, Next.js 13 has fully embraced its role in shepherding this hybrid approach to web app development and taking advantage of React Suspense, which was introduced in React 18. At the moment, it’s in beta and not recommended for production, but probably good enough for your personal website, which is what I did with thomas.wang.

Performance

My site is nearly completely static, so there won’t be significant performance benefits with the new app directory features, but I like that I will have the option to add features down the line.

Although there have been reports of the JS bundle size increasing, as a user testing the performance of my site, it loads super quickly without layout shift. So from a real-world perspective it maintains its performance.

Routing

The biggest learning curve for the new app directory is the new routing conventions, which is why the beta docs currently have it as the first main section — called “Routing Fundamentals”.

The reason this is a big shift is because it’s quite different than the previous Next.js way of having many directories at the root level, like pages and components. Now the app directory is the one directory to rule them all and contains all types of special files (e.g. page.js & head.js).

The good news is that I found I got used to the new conventions quickly and when you read the docs, things make sense and feel well thought out.

Server Components

One of the big features I’m excited about is React Server Components, which is now the default for any component created in app. Component-level server-side data fetching takes advantage of React Suspense, which streams data from the server to the UI, and enables faster loading of dynamic data with its built in parallel data fetching pattern.

The other benefit of this approach is that it allows you to co-locate your server rendered data with components, instead of having to rely on prop drilling of data from the page to the component. Before Next.js 13, the way to accomplish this was to call an API or build an API route then call fetch() from the component.

Paper Cuts

A few paper cuts / bugs I ran into:

  • head.js doesn’t work when routing on the client (Tweet from Delba)
  • You have to add an empty <head> to the root layout or you will get hydration errors (issue #41953)
  • Internationalized routing is not going to be supported, so if you have i18n in your next.config.js then you have to handle that yourself and provide fallbacks.
  • Having to specify 'use client' at the top of every client-side component feels suboptimal. It would be nice if Next.js was able to infer from the file that it’s a client component and would make that decision automatically.

Takeaway

All-in-all, this was a great release!

I’m looking forward to working with this more and thankful that Next.js continues to receive heavy investment from Vercel. It really does make web app development much more pleasant.