Next.js 12 to 13 Upgrade Guide
Introduction
If you've put off upgrading Next.js 12 to 13 because of the engineering effort, I can assure you that it's a lot less work than you think. The Next.js team also shipped tooling to automate the upgrade process for you. There are utilities called codemods which you can run from the terminal which automatically upgrades your old code
Follow me as I upgrade a codebase I am working on to Next.js 13. I will be following the official Next.js upgrade guide.
Install Next.js 13
Run following command to install the latest version of Next.js and React:
npm install next@latest react@latest react-dom@latest --save
I also upgraded to the latest version of eslint:
npm install -D eslint-config-next@latest --save
Now, I am at a point where my project is using Next.js 13, but I haven't actually made any updates to my code to make the code compatible.
Here's what we can do next: we can start the project locally to see what's broken and fix any errors that show up. Let's run the following command to start the project locally:
npm run dev
Fix Image Imports
Fix next/future/image and next/image imports
Here's the first error I ran into:
Module not found: Can't resolve 'next/future/image'
When we were on Next.js 12, we were using the Next.js 13 Image component by importing the next/future/image component instead of the next/image component The future is now, though.
All imports of next/future/image needed to be updated to next/image.
Instead of doing a find and replace throughout the codebase (or worse, going through each file to update each import line one-by-one), we can run the following codemod to do the work for us:
npx @next/codemod next-image-to-legacy-image ./
This codemod also imports any Next.js 12 image components to use the legacy version. The following import:
import Image from 'next/image'
will now be migrated to:
import Image from 'next/legacy/image'
Fix incompatible Next.js 13 image components
You may be looking at the above codemod with disappointment since you've got a lot of tech debt in the form of updating next/legacy/image imports. But, there's a codemod that can eliminate that tech debt. Run the codemod with the following command:
npx @next/codemod next-image-experimental ./
This codemod will migrate all next/legacy/image imports to use next/image by smartly deleting any deprecated props and replacing them with raw styles using the style prop.
After running the two image codemods from above, we can now move on to fixing broken next/link imports.
Fix Link components
You'll notice that using <a> tags inside of the <Link> component will result in the following error:
error - node_modules/next/dist/client/link.js (269:22) @ LinkComponent
error - Error: Invalid <Link> with <a> child. Please remove <a> or use <Link legacyBehavior>.
Learn more: https://nextjs.org/docs/messages/invalid-new-link-with-extra-anchor
You can run the new-link codemod to remove any nested <a> tags inside of the new <Link> tag:
npx @next/codemod new-link ./
This command fixed all of the Link-related component issues for my project. That's all it took to fix that issue.
Other Issues
The above codemods solved 99% of the issues I encountered when upgrading to Next.js 13. They were pretty magical in that I didn't have any run any scripts or do global find-and-replaces to rewrite any code.
It was honestly a pretty amazing experience. I was surprised that the upgrade was that easy. It probably only took me 15 minutes.
The codemods weren't perfect, though. When I clicked through the website, there were some minor UI issues. I don't know if these were caused by the codemod, or if they were caused by upgrading to Next.js 13, but there were some pretty clear UI layout violations where elements weren't where they should have been.
There were styling issues related with flex containers arranging elements in rows rather than columns. The good thing was these were pretty quick fixes.
The upgrade process was much smoother than I expected, and I have to give a shoutout to the Next.js team for providing such a good developer experience. I've been very impressed with the project overall in the last two years that I have been using Next.js.