Converting Next Pages to App Directory
Converting Next Pages to App Directory
The project that is going to be converted is a completed and working application. There is a high chance that it will have errors all over the place. This is just part of the struggle. Move a few pieces and see what errors come up. Move a few more until it seems to work. Possibly running tests along the way. It shouldn't be too much of a struggle until we get to the more complex pages. At first it will be simple(ish).
We will use the From Pages to App Vercel's NextJS guide. This will help us with the basics and find problems that we may not understand ourselves.
- The app is already at version 13. So we will not be updating the version in a major way. We will just be bumping up to the latest version.
- There is an updated:
- Image component
- Link component
- Script component
- Font optimization
-
Date fetching functions like
getServerSideProps
andgetStaticProps
have been replaced with a new API insideapp
.getStaticPaths
has been replaced withgenerateStaticParams
.
In the beginning we should note that the application needs a starting point.
There will be two different places if you're in the app directory or the pages
directory. The app directory has a layout and a page. The pages directory has a
_app
and a _document
. For the root layout.
pages/404.js
has been replaced withnot-found.js
.-
pages/api/*
currently remain inside the pages directory. What? Isn't there also an API route in the app directory? Yes, we have the ability to have both the API route in the pages and the app directory. It just changes the setup.
Let's take a look at the new setup for the layout.tsx
:
export default function RootLayout({
// Layouts must accept a children prop.
// This will be populated with nested layouts or pages
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
-
Why do we use normal html tags instead of imported
next/document
components? This is a question that we will hope to answer later. -
App directory must include the
layout
. You must define the<html>
and<body>
tags since NextJS does not automatically create them. - Root layout does replace
_app
and_document
.
You can manage the meta data in different layouts and pages with the Metadata
import.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Home',
description: 'Welcome to Next.js',
}
Migrating _document
and _app
If you have the existing _app
or _document
file, you can copy the contents
(e.g. global styles) to the root layout. The styles in the app/layout
will not
apply to the pages/*
. You should keep the _app/_document
while migrating to
prevent routes breaking. Once fully migrated you can safely delete them.
Notes about this specific project. After moving over the first component
-
With styled components we will need to use
client
components. It's not available in server components as of the writing of this post. - The
useRouter()
hook will have to be imported fromnext/navigation
.
What is the difference between server and client components?
- Client components are all of the react that we are used to in the past.
- Server components are for fetching data and sending some data back to the server.
💬 Where should the client component be. Should it be at a top level. Or should we keep as many as server components as possible. Can we keep layering these components. Client and server on top of each other without any kickback? Or do we run into problems?
Creating and moving over our first components
-
Inside of the app directory we will include a
opengraph-image.alt.txt
and aopengraph-image.png
that should get added as our tags for social medias at the top of all pages. Unless we chose to start editing the metadata using the next component for a more dynamic approach.
In the process of moving over the _app/_document
over to layout. The first
difference I notice is the fact that we don't import the Head, HTML, Main, and NextScript
. I won't be including NextScript
for this. Not 100% sure if we
need it or why. We will keep the Script
from next/script
. That will still be
used with our strategy="afterInteractive"
property.
Most of the file is just copy and pasted over. When the project is run. It was
throwing errors about how the useRouter()
needed to be imported from
next/navigation
now. Which is fine. We just went to the imported components
that required those. Switched them over and they "seemed" to work fine again. Or
at least the transpiler did not keep yelling.
- What do we do about importing the fonts from google?
import { Inconsolata, Roboto } from 'next/font/google';
const inconsolata = Inconsolata({
subsets: ['latin'],
weight: ['400', '700'],
});
const roboto = Roboto({
subsets: ['latin'],
weight: ['400', '700'],
display: 'optional',
style: ['normal','italic']
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${inconsolata.className} ${roboto.className}`}>
<head>
</head>
-
We will import
Roboto
andInconsolata
with some specific settings. Which will them be added to theclassName
so to fonts can be used across the whole project.
💬 When you're using providers they will have to be on the client side.
Adding to the head of the page
In the old format we would use the Head
component and write inside of those.
Which isn't how we do that in the app component. We will use the Metadata
import from next.
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My Page Title',
}
export default function Page() {
return '...'
}
🛑 At this point the most basic setup is moved over. We will have the beginning of the project moved over. This will allow for use to start moving over each page until we have them all over inside of the app directory. After we move everything over to the app directory. We will deleted the pages directory.
Moving over pages routes into the app directory
- What changes when we use the app directory?
We use folders and inside of those folders. There are files that have specific
uses. The main file we will use is page.tsx
. This will be the main content of
the page that we will be bringing over.
-
Let's bring over the login and the register components. This went relatively
well so far. Nothing special happened. Had to change a few
next/navigation
useRouter()
imports.
Most of the files move over really easily. If there are hooks involved we will
make sure that use client
is at the top of the page. To allow for normal
client components. We can get most pages to move over without a problem.
-
When you get query params. That style changes in Next 13 app directory to
useSearchParams()
where you can use it like.
const searchParams = useSearchParams();
const mode = searchParams?.get('mode') as mode;
const oobCode = searchParams?.get('oobCode') as string;