In React development, Next.js has always been a game-changer, especially for folks who appreciate a powerful and manageable framework. With the release of Next.js 14, things have gotten even more exciting. However, change can be challenging, and migration can be a bit daunting. Let's do this process step-by-step.
Upgrade Next.js
Step 1: Upgrade Next.js
To update to the Next.js version run the following command using your preferred package manager:
npm install next@latest react@latest react-dom@latest
Step 2: Migrating Pages to the App Directory
The first step in upgrading our website was to migrate our pages into the new app directory. This was a fairly straightforward task as we only have a single-page template to render every page on our site (we rely heavily on catch-all segments to render our pages dynamically).
![Migrating Pages to the App Directory](https://cdn.prod.website-files.com/6470768de8327f36a7ae11a5/6694e67af0872db52ebcfc34_6694c1ed8888a1a508cecbac_AD_4nXcEX-1Nf5XoEjP9vZJtvK1mYPgGKaiBXKoyVAXsTnfE5-X83_g0ZVW3CaTYjNVY9bt10teJLWXcIftX6-ZPG9u_iWuTTfzZ-U7QDgxp2SoJZATbYgLjaNYlqtgH-jqAEIGIwNybMVeFffMZJfxTONX-nh4.png)
Step 3: Migrating Data Fetching Methods
The next step in the migration was changing how we fetch data. In Next.js 12 we relied on the getServerSideProps function to fetch data from our backend and feed that data into our components.
Next.js 14 removes this function in favor of fetching data directly inside your component. This is also a fairly easy change as we just needed to move our data fetching code into our page component.
Our old Next.js code looked something like this (please note that this code is drastically simplified for demonstration purposes),
// app/page.jsx
export default async function Home({ data }) {
return (
<div>
<h1>Posts</h1>
<ul>
{data.map((post) => (
<li key="{post.id}">{post.title}</li>
))}
</ul>
</div>
);
}
export async function getServerSideProps() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
return {
props: {
data: data,
},
};
}
After the migration to Next.js 14, we had something like this:
// app/page.jsx
export default async function Home() {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
return (
<div>
<h1>Posts</h1>
<ul>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
Step 4: Migrating Metadata
In Next.js 12, we would use the next/head component to render our metadata, but that was removed in favor of the generateMetadata function in Next.js 14.
Old Code looks like,
<Head>
<title>{metadata.title}</title>
<meta name="description" content={metadata.description} />
</Head>;
After Migration,
const metadata = {
title: metadata.title,
description: metadata.description,
};
Step 5: Migrate routing hooks
A new router has been added to support the new behavior in the app directory.
In the app, you should use the three new hooks imported from next/navigation: useRouter(), usePathname(), and useSearchParams(). The new useRouter hook is imported from next/navigation and has different behavior to the useRouter hook in pages which is imported from next/router. The useRouter hook imported from next/router is not supported in the app directory but can continue to be used in the pages directory.
Step 6: Layouts
Next.js 13+ introduced the concept of layout files – components that wrap multiple pages on your website.
In Next.js 12, we set up layouts by simply wrapping every page in a layout component.
In Next.js 13+, we could eliminate the need to manually wrap our pages in a layout component by using a layout file. This was a fairly easy change as we just needed to move our existing layout components into a layout.tsx file.
Other Changes
- Adding the “use client” directive to any of our client components that required state or interactivity.
- Convert getStaticPaths method to generateStaticParams.
- The next export command has been removed in favor of output: ‘export’ config.
Conclusion
Next.js 14 is a large paradigm shift from the previous versions, but learning and embracing those changes can bring huge advantages to your website. Not only does it make it easier to manage layouts, routing, and caching, but it also comes with significant performance improvements.