Upgrading From NextJS v12 to v13
4 min read
If y'll didn't already know, I use NextJS to run this website. I had been using NextJS v12 up until yesterday when I pushed some changes to upgrade to v13. π Prior to this, I spent a couple of weeks playing around with the upgrade, to understand what changes were needed to get an app upgraded and running in production.
The reason I did this was: (i) because it's fun to tinker, but more importantly (ii) I wanted to propose upgrading my team's NextJS app and needed to get a solid, working understanding before being able to convince my teammates to go along with the idea. That's one of the benefits of having a personal project - it allows you to mess around with new technology before deciding whether it's something worth pursuing when the risks are higher. π
I've now done the upgrade for both apps, and am happy to report that there were not a lot of issues to untangle. Much has been written about the NextJS v13 upgrade process and features, so I won't go into those in-depth here. I wrote an internal blog post for my team mates though, as a sort of TL;DR for the official docs, so I'll just reproduce the main points here.
Main changes needed to get the app working
General package amendments and upgrading to React v18
- Upgrading
react
andreact-dom
to v18, along with theeslint-config-next
package and relevant@types
packages. - Upgrading
babel-plugin-styled-components
. - React v18 is stricter about improper nested HTML elements, so needed to fix a few instances of nested
<p>
tags within other<p>
tags that were coming in from our CMS. - Upgraded all the
@testing-library
packages and deleted the@testing-library/react-hooks
package, since this is now part of the main@testing-libray/react
package.- Needed to fix some failing tests as a result of this:
waitForNextUpdate
no longer exists when usingrenderHook
.waitfor
should be used instead.- React v18 seems stricter around proper use of
act
andwaitFor
when you're having to wait for React render cycles to complete.
- Needed to fix some failing tests as a result of this:
- Fixing Typescript compilation errors in a number of our components (like our payment provider mock and router mock) due to missing functions.
NextJS v13 specific changes
- Removing
next-transpile-modules
package as it's now in-built into v13 and no longer needed.- Amended
next.config.js
to account for this (we were using it to load in specific packages).
- Amended
- Amending any width and height props that were being passed to the
Image
component as strings (instead of numbers). - NextJS v12's
Image
component is now imported fromnext/legacy/image
component. Importing fromnext/image
means using the new v13Image
component.- A big difference is that NextJS has simplified how the final
img
element is rendered with the removal of all the extraneous<span>
tags, wrapping<img>
. This means it's a lot easier to directly style the<img>
element. - There's also better image optimisation and faster lazy loading out of the box.
- A big difference is that NextJS has simplified how the final
- NextJS v13's
Link
component no longer accepts an<a>
tag as a child - it should be text instead. ππ»- If the underlying component is not text, e.g. a Styled Component or a button, we should add the
passHref
property. - A new eslint rule has been added to warn us in instances when the
passHref
should be used but is missing.
- If the underlying component is not text, e.g. a Styled Component or a button, we should add the
- I went through all pages where we were using the
Link
andImage
components to check that all was rendering properly with the v13 versions, and made appropriate changes where needed.
Other benefits of upgrading to NextJS v13
- Uses React 18 (read more about the changes here).
- The biggest addition is opt-in concurrent React and Suspense.
- Auto-batching of multiple state changes into a single re-render is also a nice add-on.
- New
next/font
component that helps minimise layout shift for self-hosted fonts. - New routing methodology with the introduction of the
app
directory, that's built on top of React Server Components.- Features support for layouts, nested routing, loading states and error handling. Read more about it here.
- Option to use faster Turbopack over Webpack (but realistically, weβre not really concerned with this at the moment). This is only available for testing in the dev environment.
Next steps
- Implement
next/font
. It seems like a simple change. More can be read about why we might want to use it here. - Wait for the
app
directory feature to be released out of beta before taking the decision on whether to move across to the new structure. Vercel does not currently recommend that this feature is used in production just yet.