Pages から App へ
このガイドでは以下のことを説明します。
- Next.js アプリケーションをバージョン 12 からバージョン 13 へ更新する
- pagesディレクトリと- appディレクトリの両方で機能する機能をアップグレードする
- 既存のアプリケーションを pagesからappへ段階的に移行する
アップグレード
Node.js のバージョン
最小 Node.js バージョンは v18.17 です。詳細については Node.js ドキュメントを参照してください。
Next.js のバージョン
Next.js バージョン 13 に更新するには、お好みのパッケージマネージャーを使用して以下のコマンドを実行してください。
npm install next@latest react@latest react-dom@latestESLint のバージョン
ESLint を使用している場合、ESLint のバージョンをアップグレードする必要があります。
npm install -D eslint-config-next@latestヒント: ESLint の変更を適用するには、VS Code で ESLint サーバーを再起動する必要がある場合があります。コマンドパレット (Mac の場合は
cmd+shift+p; Windows の場合はctrl+shift+p) を開き、ESLint: Restart ESLint Serverを検索してください。
次のステップ
更新後、次のステップについては以下のセクションを参照してください。
- 新機能のアップグレード: 改善された Image および Link コンポーネントなどの新機能にアップグレードするためのガイドです。
- pagesディレクトリから- appディレクトリへの移行:- pagesから- appディレクトリへ段階的に移行するためのステップバイステップガイドです。
新機能のアップグレード
Next.js 13 では、新しい機能と規約を備えた新しい App Router が導入されました。新しい Router は app ディレクトリで利用でき、pages ディレクトリと共存します。
Next.js 13 へのアップグレードは App Router の使用を必須とはしません。更新された Image コンポーネント、Link コンポーネント、Script コンポーネント、フォントの最適化など、両方のディレクトリで機能する新機能を pages で引き続き使用できます。
<Image/> コンポーネント
Next.js 12 では、一時的なインポート next/future/image を使用して Image コンポーネントに新しい改善が導入されました。これらの改善には、クライアントサイド JavaScript の削減、画像の拡張とスタイリングの簡単な方法、アクセシビリティの向上、ネイティブブラウザの遅延ロードが含まれていました。
バージョン 13 では、この新しい動作が next/image のデフォルトになりました。
新しい Image コンポーネントへの移行に役立つ 2 つの codemod があります。
- next-image-to-legacy-imagecodemod:- next/imageのインポートを安全かつ自動的に- next/legacy/imageに変更します。既存のコンポーネントは同じ動作を維持します。
- next-image-experimentalcodemod: インラインスタイルを危険にさらす形で追加し、使用されていないプロップを削除します。これにより、既存のコンポーネントの動作が新しいデフォルトに一致するように変更されます。この codemod を使用するには、まず- next-image-to-legacy-imagecodemod を実行する必要があります。
<Link> コンポーネント
The <Link> コンポーネントは、子として <a> タグを手動で追加する必要がなくなりました。この動作は バージョン 12.2で実験的なオプションとして追加され、現在はデフォルトです。Next.js 13 では、<Link> は常に <a> をレンダリングし、基になるタグにプロップを転送できます。
例:
import Link from 'next/link'
 
// Next.js 12: `<a>` has to be nested otherwise it's excluded
<Link href="/about">
  <a>About</a>
</Link>
 
// Next.js 13: `<Link>` always renders `<a>` under the hood
<Link href="/about">
  About
</Link>Next.js 13 にリンクをアップグレードするには、new-link codemod を使用できます。
<Script> コンポーネント
next/script の動作は pages と app の両方をサポートするように更新されましたが、スムーズな移行を確実にするためにいくつかの変更が必要です。
- 以前 _document.jsに含めていたbeforeInteractiveスクリプトは、ルートレイアウトファイル (app/layout.tsx) に移動してください。
- 実験的な workerストラテジーはまだappでは動作せず、このストラテジーで指定されたスクリプトは削除するか、別のストラテジー (例:lazyOnload) を使用するように変更する必要があります。
- onLoad、- onReady、および- onErrorハンドラーはサーバーコンポーネントでは動作しないため、クライアントコンポーネントに移動するか、完全に削除するようにしてください。
フォントの最適化
以前は、Next.js は フォント CSS をインライン化することでフォントの最適化を支援していました。バージョン 13 では、新しい next/font モジュールが導入され、優れたパフォーマンスとプライバシーを確保しつつ、フォントの読み込みエクスペリエンスをカスタマイズできるようになりました。next/font は pages ディレクトリと app ディレクトリの両方でサポートされています。
CSS のインライン化は pages では引き続き機能しますが、app では機能しません。代わりに next/font を使用してください。
next/font の使用方法については、フォントの最適化ページを参照してください。
pages から app への移行
🎥 視聴: App Router を段階的に採用する方法について学びましょう → YouTube (16 分)。
App Router への移行は、Next.js が構築されている React の機能、例えばサーバーコンポーネント、Suspense などを初めて使用することになるかもしれません。特殊なファイルや レイアウトなどの新しい Next.js の機能と組み合わせると、移行には新しい概念、メンタルモデル、行動の変化を学ぶ必要があります。
これらの更新の複合的な複雑さを軽減するために、移行をより小さなステップに分割することをお勧めします。app ディレクトリは、pages ディレクトリと同時に動作するように意図的に設計されており、ページごとの段階的な移行を可能にします。
- appディレクトリはネストされたルーティングとレイアウトをサポートしています。詳細はこちら。
- ネストされたフォルダーを使用してルーティングを定義し、特別な page.jsファイルを使用してルーティングセグメントを公開します。詳細はこちら。
- 各ルーティングセグメントの UI を作成するために特殊なファイル規約が使用されます。最も一般的な特殊ファイルは page.jsとlayout.jsです。- ルーティングに固有の UI を定義するには page.jsを使用します。
- 複数のルーティング間で共有される UI を定義するには layout.jsを使用します。
- 特殊ファイルには .js、.jsx、または.tsxのファイル拡張子を使用できます。
 
- ルーティングに固有の UI を定義するには 
- コンポーネント、スタイル、テストなど、他のファイルを appディレクトリ内に共存させることができます。詳細はこちら。
- getServerSidePropsや- getStaticPropsのようなデータフェッチ関数は、- app内の 新しい API に置き換えられました。- getStaticPathsは- generateStaticParamsに置き換えられました。
- pages/_app.jsと- pages/_document.jsは、単一の- app/layout.jsルートレイアウトに置き換えられました。詳細はこちら。
- pages/_error.jsは、より詳細な- error.js特殊ファイルに置き換えられました。詳細はこちら。
- pages/404.jsは、- not-found.jsファイルに置き換えられました。
- pages/api/*の API ルーティングは、- route.js(ルートハンドラー) 特殊ファイルに置き換えられました。
ステップ 1: app ディレクトリの作成
最新の Next.js バージョンに更新する (13.4 以上が必要)
npm install next@latest次に、プロジェクトのルート (または src/ ディレクトリ) に新しい app ディレクトリを作成します。
ステップ 2: ルートレイアウトの作成
app ディレクトリ内に新しい app/layout.tsx ファイルを作成します。これは、app 内のすべてのルーティングに適用される ルートレイアウトです。
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>
  )
}- appディレクトリにはルートレイアウトを含める必要があります。
- Next.js は <html>および<body>タグを自動的に作成しないため、ルートレイアウトはこれらを定義する必要があります。
- ルートレイアウトは pages/_app.tsxおよびpages/_document.tsxファイルを置き換えます。
- レイアウトファイルには .js、.jsx、または.tsxの拡張子を使用できます。
<head> HTML 要素を管理するには、組み込みの SEO サポートを使用できます。
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'Home',
  description: 'Welcome to Next.js',
}_document.js と _app.js の移行
既存の _app または _document ファイルがある場合は、その内容 (例: グローバルスタイル) をルートレイアウト (app/layout.tsx) にコピーできます。app/layout.tsx のスタイルは pages/* には適用されません。pages/* のルーティングが壊れるのを防ぐため、移行中は _app/_document を維持する必要があります。完全に移行が完了したら、それらを安全に削除できます。
React Context プロバイダーを使用している場合は、それらをクライアントコンポーネントに移動する必要があります。
getLayout() パターンのレイアウトへの移行 (オプション)
Next.js は、pages ディレクトリでページごとのレイアウトを実現するために、Page コンポーネントにプロパティを追加することを推奨していました。このパターンは、app ディレクトリの ネストされたレイアウトのネイティブサポートに置き換えることができます。
前後の例を参照
変更前
export default function DashboardLayout({ children }) {
  return (
    <div>
      <h2>My Dashboard</h2>
      {children}
    </div>
  )
}import DashboardLayout from '../components/DashboardLayout'
 
export default function Page() {
  return <p>My Page</p>
}
 
Page.getLayout = function getLayout(page) {
  return <DashboardLayout>{page}</DashboardLayout>
}変更後
- 
pages/dashboard/index.jsからPage.getLayoutプロパティを削除し、appディレクトリへのページの移行手順に従ってください。app/dashboard/page.jsexport default function Page() { return <p>My Page</p> }
- 
DashboardLayoutの内容を新しいクライアントコンポーネントに移動して、pagesディレクトリの動作を維持します。app/dashboard/DashboardLayout.js'use client' // this directive should be at top of the file, before any imports. // This is a Client Component export default function DashboardLayout({ children }) { return ( <div> <h2>My Dashboard</h2> {children} </div> ) }
- 
appディレクトリ内の新しいlayout.jsファイルにDashboardLayoutをインポートします。app/dashboard/layout.jsimport DashboardLayout from './DashboardLayout' // This is a Server Component export default function Layout({ children }) { return <DashboardLayout>{children}</DashboardLayout> }
- 
DashboardLayout.js(クライアントコンポーネント) の非インタラクティブな部分をlayout.js(サーバーコンポーネント) に段階的に移動することで、クライアントに送信するコンポーネントの JavaScript の量を減らすことができます。
ステップ 3: next/head の移行
pages ディレクトリでは、next/head React コンポーネントが title や meta などの <head> HTML 要素を管理するために使用されます。app ディレクトリでは、next/head は新しい組み込みの SEO サポートに置き換えられます。
変更前
import Head from 'next/head'
 
export default function Page() {
  return (
    <>
      <Head>
        <title>My page title</title>
      </Head>
    </>
  )
}変更後
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'My Page Title',
}
 
export default function Page() {
  return '...'
}ステップ 4: ページの移行
- appディレクトリ内のページは、デフォルトでサーバーコンポーネントです。これは、ページがクライアントコンポーネントである- pagesディレクトリとは異なります。
- appではデータフェッチが変更されました。- getServerSideProps、- getStaticProps、- getInitialPropsはよりシンプルな API に置き換えられました。
- appディレクトリは、ネストされたフォルダーを使用してルーティングを定義し、特別な- page.jsファイルを使用してルーティングセグメントを公開します。
- 
pagesディレクトリappディレクトリルーティング index.jspage.js/about.jsabout/page.js/aboutblog/[slug].jsblog/[slug]/page.js/blog/post-1
ページの移行を 2 つの主要なステップに分解することをお勧めします。
- ステップ 1: デフォルトでエクスポートされた Page コンポーネントを新しいクライアントコンポーネントに移動します。
- ステップ 2: 新しいクライアントコンポーネントを appディレクトリ内の新しいpage.jsファイルにインポートします。
ヒント: これは、
pagesディレクトリに最も近い動作を持つため、最も簡単な移行パスです。
ステップ 1: 新しいクライアントコンポーネントの作成
- appディレクトリ内に新しい別のファイル (例:- app/home-page.tsxまたは類似) を作成し、クライアントコンポーネントをエクスポートします。クライアントコンポーネントを定義するには、ファイルの先頭 (任意のインポートの前) に- 'use client'ディレクティブを追加します。- Pages Router と同様に、初回ページロード時にクライアントコンポーネントを静的 HTML にプリレンダリングするための最適化ステップがあります。
 
- デフォルトでエクスポートされたページコンポーネントを pages/index.jsからapp/home-page.tsxに移動します。
'use client'
 
// This is a Client Component (same as components in the `pages` directory)
// It receives data as props, has access to state and effects, and is
// prerendered on the server during the initial page load.
export default function HomePage({ recentPosts }) {
  return (
    <div>
      {recentPosts.map((post) => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  )
}ステップ 2: 新しいページの作成
- 
appディレクトリ内に新しいapp/page.tsxファイルを作成します。これはデフォルトでサーバーコンポーネントです。
- 
home-page.tsxクライアントコンポーネントをページにインポートします。
- 
pages/index.jsでデータをフェッチしていた場合は、新しいデータフェッチ API を使用して、データフェッチロジックを直接サーバーコンポーネントに移動してください。データフェッチのアップグレードガイドで詳細を確認してください。app/page.tsx// Import your Client Component import HomePage from './home-page' async function getPosts() { const res = await fetch('https://...') const posts = await res.json() return posts } export default async function Page() { // Fetch data directly in a Server Component const recentPosts = await getPosts() // Forward fetched data to your Client Component return <HomePage recentPosts={recentPosts} /> }
- 
以前のページで useRouterを使用していた場合は、新しいルーティングフックに更新する必要があります。詳細はこちら。
- 
開発サーバーを起動し、 https://:3000にアクセスしてください。既存のインデックスルーティングが、app ディレクトリを介して提供されているのを確認できるはずです。
ステップ 5: ルーティングフックの移行
app ディレクトリの新しい動作をサポートするために、新しいルーターが追加されました。
app では、next/navigation からインポートされる新しい 3 つのフックを使用する必要があります: useRouter()、usePathname()、および useSearchParams()。
- 新しい useRouterフックはnext/navigationからインポートされ、pagesでnext/routerからインポートされるuseRouterフックとは異なる動作をします。- next/routerからインポートされる- useRouterフックは- appディレクトリではサポートされていませんが、- pagesディレクトリでは引き続き使用できます。
 
- 新しい useRouterはpathname文字列を返しません。代わりに別のusePathnameフックを使用してください。
- 新しい useRouterはqueryオブジェクトを返しません。検索パラメータと動的ルーティングパラメータは現在分離されています。代わりにuseSearchParamsおよびuseParamsフックを使用してください。
- ページ変更をリッスンするには、useSearchParamsとusePathnameを一緒に使用できます。ルーターイベントのセクションで詳細を確認してください。
- これらの新しいフックはクライアントコンポーネントでのみサポートされています。サーバーコンポーネントでは使用できません。
'use client'
 
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
 
export default function ExampleClientComponent() {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()
 
  // ...
}さらに、新しい useRouter フックには以下の変更点があります。
- fallbackが置き換えられたため、- isFallbackは削除されました。
- locale、- locales、- defaultLocales、- domainLocalesの値は、- appディレクトリでは組み込みの i18n Next.js 機能が不要になったため削除されました。i18n について詳細はこちら。
- basePathは削除されました。代替手段は- useRouterの一部にはなりません。まだ実装されていません。
- 新しいルーターから asの概念が削除されたため、asPathは削除されました。
- isReadyは不要になったため削除されました。静的レンダリング中、- useSearchParams()フックを使用するコンポーネントは、プリレンダリングステップをスキップし、実行時にクライアントでレンダリングされます。
- routeは削除されました。- usePathnameまたは- useSelectedLayoutSegments()が代替手段を提供します。
pages と app 間でのコンポーネントの共有
pages ルーターと app ルーター間でコンポーネントの互換性を保つには、next/compat/router からの useRouter フックを参照してください。これは pages ディレクトリの useRouter フックですが、ルーター間でコンポーネントを共有する際に使用することを意図しています。app ルーターでのみ使用する準備ができたら、新しい next/navigation からの useRouter に更新してください。
ステップ 6: データフェッチメソッドの移行
pages ディレクトリは、ページデータをフェッチするために getServerSideProps と getStaticProps を使用します。app ディレクトリ内では、これらの以前のデータフェッチ関数は、fetch() と async React Server Components をベースにしたよりシンプルな API に置き換えられます。
export default async function Page() {
  // This request should be cached until manually invalidated.
  // Similar to `getStaticProps`.
  // `force-cache` is the default and can be omitted.
  const staticData = await fetch(`https://...`, { cache: 'force-cache' })
 
  // This request should be refetched on every request.
  // Similar to `getServerSideProps`.
  const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
 
  // This request should be cached with a lifetime of 10 seconds.
  // Similar to `getStaticProps` with the `revalidate` option.
  const revalidatedData = await fetch(`https://...`, {
    next: { revalidate: 10 },
  })
 
  return <div>...</div>
}サーバーサイドレンダリング (getServerSideProps)
pages ディレクトリでは、getServerSideProps がサーバーでデータをフェッチし、ファイル内のデフォルトでエクスポートされた React コンポーネントにプロップを転送するために使用されます。ページの初期 HTML はサーバーからプリレンダリングされ、その後ブラウザでページが「ハイドレート」されます (インタラクティブになります)。
// `pages` directory
 
export async function getServerSideProps() {
  const res = await fetch(`https://...`)
  const projects = await res.json()
 
  return { props: { projects } }
}
 
export default function Dashboard({ projects }) {
  return (
    <ul>
      {projects.map((project) => (
        <li key={project.id}>{project.name}</li>
      ))}
    </ul>
  )
}App Router では、サーバーコンポーネントを使用して、React コンポーネント内にデータフェッチを配置できます。これにより、クライアントに送信する JavaScript を減らしつつ、サーバーからレンダリングされた HTML を維持できます。
cache オプションを no-store に設定することで、フェッチされたデータはキャッシュされないことを示すことができます。これは pages ディレクトリの getServerSideProps に似ています。
// `app` directory
 
// This function can be named anything
async function getProjects() {
  const res = await fetch(`https://...`, { cache: 'no-store' })
  const projects = await res.json()
 
  return projects
}
 
export default async function Dashboard() {
  const projects = await getProjects()
 
  return (
    <ul>
      {projects.map((project) => (
        <li key={project.id}>{project.name}</li>
      ))}
    </ul>
  )
}リクエストオブジェクトへのアクセス
pages ディレクトリでは、Node.js HTTP API に基づいてリクエストベースのデータを取得できます。
たとえば、getServerSideProps から req オブジェクトを取得し、それを使用してリクエストのクッキーとヘッダーを取得できます。
// `pages` directory
 
export async function getServerSideProps({ req, query }) {
  const authHeader = req.getHeaders()['authorization'];
  const theme = req.cookies['theme'];
 
  return { props: { ... }}
}
 
export default function Page(props) {
  return ...
}app ディレクトリは、リクエストデータを取得するための新しい読み取り専用関数を公開しています。
- headers: Web Headers API に基づいており、サーバーコンポーネント内で使用してリクエストヘッダーを取得できます。
- cookies: Web Cookies API に基づいており、サーバーコンポーネント内で使用してクッキーを取得できます。
// `app` directory
import { cookies, headers } from 'next/headers'
 
async function getData() {
  const authHeader = (await headers()).get('authorization')
 
  return '...'
}
 
export default async function Page() {
  // You can use `cookies` or `headers` inside Server Components
  // directly or in your data fetching function
  const theme = (await cookies()).get('theme')
  const data = await getData()
  return '...'
}静的サイト生成 (getStaticProps)
pages ディレクトリでは、getStaticProps 関数がビルド時にページをプリレンダリングするために使用されます。この関数は、外部 API またはデータベースからデータをフェッチし、ビルド中に生成されるページ全体にこのデータを渡すために使用できます。
// `pages` directory
 
export async function getStaticProps() {
  const res = await fetch(`https://...`)
  const projects = await res.json()
 
  return { props: { projects } }
}
 
export default function Index({ projects }) {
  return projects.map((project) => <div>{project.name}</div>)
}app ディレクトリでは、fetch() によるデータフェッチはデフォルトで cache: 'force-cache' になり、これは手動で無効化されるまでリクエストデータをキャッシュします。これは pages ディレクトリの getStaticProps に似ています。
// `app` directory
 
// This function can be named anything
async function getProjects() {
  const res = await fetch(`https://...`)
  const projects = await res.json()
 
  return projects
}
 
export default async function Index() {
  const projects = await getProjects()
 
  return projects.map((project) => <div>{project.name}</div>)
}動的パス (getStaticPaths)
pages ディレクトリでは、getStaticPaths 関数がビルド時にプリレンダリングされるべき動的パスを定義するために使用されます。
// `pages` directory
import PostLayout from '@/components/post-layout'
 
export async function getStaticPaths() {
  return {
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
  }
}
 
export async function getStaticProps({ params }) {
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
 
  return { props: { post } }
}
 
export default function Post({ post }) {
  return <PostLayout post={post} />
}app ディレクトリでは、getStaticPaths は generateStaticParams に置き換えられます。
generateStaticParams は getStaticPaths と同様に動作しますが、ルーティングパラメータを返すための簡素化された API を持ち、レイアウト内で使用できます。generateStaticParams の戻り値の形式は、ネストされた param オブジェクトの配列や解決されたパスの文字列ではなく、セグメントの配列です。
// `app` directory
import PostLayout from '@/components/post-layout'
 
export async function generateStaticParams() {
  return [{ id: '1' }, { id: '2' }]
}
 
async function getPost(params) {
  const res = await fetch(`https://.../posts/${(await params).id}`)
  const post = await res.json()
 
  return post
}
 
export default async function Post({ params }) {
  const post = await getPost(params)
 
  return <PostLayout post={post} />
}app ディレクトリの新しいモデルでは、getStaticPaths よりも generateStaticParams という名前の方が適切です。get プレフィックスは、getStaticProps と getServerSideProps が不要になった今、単独でより適切に機能する、より記述的な generate に置き換えられます。Paths サフィックスは、複数の動的セグメントを持つネストされたルーティングにより適切な Params に置き換えられます。
fallback の置き換え
pages ディレクトリでは、getStaticPaths から返される fallback プロパティは、ビルド時にプリレンダリングされないページの動作を定義するために使用されます。このプロパティは、ページ生成中にフォールバックページを表示するために true に設定するか、404 ページを表示するために false に設定するか、リクエスト時にページを生成するために blocking に設定できます。
// `pages` directory
 
export async function getStaticPaths() {
  return {
    paths: [],
    fallback: 'blocking'
  };
}
 
export async function getStaticProps({ params }) {
  ...
}
 
export default function Post({ post }) {
  return ...
}app ディレクトリでは、config.dynamicParams プロパティが、generateStaticParams 外のパラメータの処理方法を制御します。
- true: (デフォルト)- generateStaticParamsに含まれていない動的セグメントはオンデマンドで生成されます。
- false:- generateStaticParamsに含まれていない動的セグメントは 404 を返します。
これは pages ディレクトリの getStaticPaths の fallback: true | false | 'blocking' オプションを置き換えるものです。fallback: 'blocking' オプションは dynamicParams に含まれていません。これは、ストリーミングでは 'blocking' と true の違いが無視できるほど小さいためです。
// `app` directory
 
export const dynamicParams = true;
 
export async function generateStaticParams() {
  return [...]
}
 
async function getPost(params) {
  ...
}
 
export default async function Post({ params }) {
  const post = await getPost(params);
 
  return ...
}dynamicParams が true (デフォルト) に設定されている場合、生成されていないルーティングセグメントがリクエストされると、それはサーバーレンダリングされ、キャッシュされます。
インクリメンタル静的再生成 (getStaticProps と revalidate)
pages ディレクトリでは、getStaticProps 関数を使用すると、revalidate フィールドを追加して、一定時間後にページを自動的に再生成できます。
// `pages` directory
 
export async function getStaticProps() {
  const res = await fetch(`https://.../posts`)
  const posts = await res.json()
 
  return {
    props: { posts },
    revalidate: 60,
  }
}
 
export default function Index({ posts }) {
  return (
    <Layout>
      <PostList posts={posts} />
    </Layout>
  )
}app ディレクトリでは、fetch() によるデータフェッチで revalidate を使用できます。これにより、指定された秒数の間リクエストがキャッシュされます。
// `app` directory
 
async function getPosts() {
  const res = await fetch(`https://.../posts`, { next: { revalidate: 60 } })
  const data = await res.json()
 
  return data.posts
}
 
export default async function PostList() {
  const posts = await getPosts()
 
  return posts.map((post) => <div>{post.name}</div>)
}API ルーティング
API ルーティングは pages/api ディレクトリで変更なしで引き続き機能します。ただし、app ディレクトリではルートハンドラーに置き換えられました。
ルートハンドラーを使用すると、Web Request および Response API を使用して、特定のルーティングに対するカスタムリクエストハンドラーを作成できます。
export async function GET(request: Request) {}ヒント: 以前にクライアントから外部 API を呼び出すために API ルーティングを使用していた場合、代わりにサーバーコンポーネントを使用して安全にデータをフェッチできるようになりました。データフェッチについて詳細はこちら。
シングルページアプリケーション
同時にシングルページアプリケーション (SPA) から Next.js へ移行している場合は、詳細については弊社のドキュメントを参照してください。
ステップ 7: スタイリング
pages ディレクトリでは、グローバルスタイルシートは pages/_app.js のみに制限されていました。app ディレクトリでは、この制限が解除されました。グローバルスタイルは、任意のレイアウト、ページ、またはコンポーネントに追加できます。
Tailwind CSS
Tailwind CSS を使用している場合、tailwind.config.js ファイルに app ディレクトリを追加する必要があります。
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}', // <-- Add this line
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
  ],
}また、app/layout.js ファイルでグローバルスタイルをインポートする必要もあります。
import '../styles/globals.css'
 
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}Tailwind CSS でのスタイリングについて詳細はこちら。
App Router と Pages Router の併用
異なる Next.js ルーターによって提供されるルーティング間を移動すると、ハードナビゲーションが発生します。next/link を使用した自動リンクプリフェッチは、ルーター間でプリフェッチを行いません。
代わりに、App Router と Pages Router 間のナビゲーションを最適化して、プリフェッチされた高速なページ遷移を維持できます。詳細はこちら。
Codemods
Next.js は、機能が非推奨になったときにコードベースをアップグレードするのに役立つ Codemod 変換を提供します。詳細についてはCodemodsを参照してください。
お役に立ちましたか?