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
getServerSidePropsandgetStaticPropshave been replaced with a new API insideapp.getStaticPathshas 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.jshas 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/documentcomponents? 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
_appand_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
clientcomponents. 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.txtand aopengraph-image.pngthat 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
RobotoandInconsolatawith some specific settings. Which will them be added to theclassNameso 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/navigationuseRouter()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;