It's been a wild ride
Gatsby has been my go-to for quite a while. I love the simplicity (is it?) of it and how easy it is to setup a project. I do sometimes forget that there is "the Gatsby way of doing things" with regard to plugins but once you are set in the ecosystem, and you grasp the build process, you are golden with creating your static sites. Understand the data, understand how to statically build your site.
Large organizations have embraced this for what it brings and I have been helping them along their journey to utilize these tools to build their sites for years. I love watching these frameworks grow and in the end you choose the best tool for the project.
For me, today marks a departure from Gatsby as my go-to and instead reaching back to an old friend: Next.js.
Looking back on an old project, I can see that I was using Next.js when it was at version
4.2.3. Actually, that was when I left that project so it may have been at v3 but the point being ... we are now at version
13.3.2. So much has changed.
Yes, there was a time when we didn't have dynamic routes!
With the release of v13 and the app directory, I decided to move this little project over to Next.js in order to gain experience with the new features and get a better understanding of what the future looks like.
The future is bright
And damn, I like it. In a very good way. There are many improvements under the hood that one might say it makes their head spin. This is a departure from the old and ushers in a brand new. Granted, there are some minor gripes (sooo many
page.tsx files; which one am I looking at again?) however the fact that the structure is intentionally explicit is very appealing to me.
A page now defaults to simply being a server component however should you want to make it a client component? Go for it. All you need to do is to add the
'use client' directive.
A page has to be named (appropriately)
page.tsx|.jsx|.js and will be public. As is the usual convention for routing, create a directory and put your page in there for a nested route. Thus you will end up with something like
src/app/about/page.tsx and for a dynamic route,
src/app/blog/[slug]/page.tsx. See what I mean about having a lot of "page" files?
However, this plays nicely with other features (custom layout/error) for each route and these can also be shared amongst grouped routes.
Data fetching is much more intuitive now. No more
getStaticProps and instead we simply fetch our data from within the component (page) itself and use the data. Code is simpler, easier to read, and easier to understand the source of your data.
We no longer have the
_document files and instead move, again, a more explicit structure with Layouts. The only required layout file,
layout.tsx|.jsx|.js, (much like root page file) is at the root and will be shared by all defined pages. As mentioned, a defined route can have it's own layout file which will be wrapped by any others above in the hierarchy. Note that unlike a page, a layout cannot be a server component.
Fun facts (as per docs):
- Layouts can fetch data.
- Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will automatically dedupe the requests without affecting performance.
Much like layouts, we can use the new Loading UI to create a loading file that will instantly show a meaningful loading state to the user to indicate to the user that the page is loading and this will be immediately swapped when data is ready.
And again, much like we can have specific layouts for pages, the same convention follows: each page can have its own loading file.
Are you seeing the pattern yet? Just like layouts and loading, we can create separate error handlers inside a nested route to handle any errors that occur within that segment. One difference to note: these must be client components.
Check out the documentation for further details around the finer details of handling errors in layouts as well as a global error handler.
The above mentioned are large changes however we can't forget some of the smaller changes that are also different from how we have recently been working with Next.js. Things like the introduction of a new
next/font module for better font optimization, the Link component no longer needing a nested anchor tag, and route handlers have also become more obvious in how they are created.
One down side I encountered while testing fonts is that some of the more nuanced features of certain fonts aren't (yet?) supported. For example, when using the Google Font Inter I was unable to use the
font-feature-settings: "salt" correctly via CSS nor is there a way to set this when using the
For teams with existing projects using the pages convention, rest assured that you can continue to use your pages as is with Next.js 13 and can progressively upgrade. I don't envy large codebases that will have to go through this however I, personally, would love to take on that challenge!
Be forewarned, if using MUI or Emotion, at the time of writing there are a few open GitHub issues that one should be aware of:
As always, the upgrade documentation will guide you through what needs to be updated and how to do it with complete examples. Things are still being worked on so the folks at Vercel tell us that this isn't ready for production just yet.
That's fine for me, I want to kick the tires around a bit. If I can't have a preview just yet, no problem. I can see it's currently in progress by taking a peek at the roadmap.
Gatsby and I have had a wonderful relationship. I still have a few projects using it so this isn't a goodbye so much as it is a refocus of attention. I'm excited by the new architecture and am impressed with the forward thinking that Next.js brings.
I'm also looking forward to when this is ready for prime time!
- No more roadmap that I can find since it's stable since v13.4
- All beta documentation links updated