App Routerインクリメンタル導入ガイド
このガイドは以下の内容をサポートします:
- 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@latest
ESLintバージョン
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つあります:
next-image-to-legacy-image
コードモッド:next/image
インポートをnext/legacy/image
に安全かつ自動的に名前変更します。既存のコンポーネントは同じ動作を維持します。next-image-experimental
コードモッド:インラインスタイルを危険に追加し、未使用のpropsを削除します。これにより、既存のコンポーネントの動作が変更され、新しいデフォルトに一致します。このコードモッドを使用するには、まずnext-image-to-legacy-image
コードモッドを実行する必要があります。
<Link>
コンポーネント
<Link>
コンポーネントは、子として<a>
タグを手動で追加する必要がなくなりました。この動作はバージョン12.2で実験的オプションとして追加され、現在はデフォルトになっています。Next.js 13では、<Link>
は常に<a>
をレンダリングし、基礎となるタグにpropsを転送できます。
例:
import Link from 'next/link'
// Next.js 12: `<a>`をネストしないと除外される
<Link href="/about">
<a>About</a>
</Link>
// Next.js 13: `<Link>`は常に内部的に`<a>`をレンダリングする
<Link href="/about">
About
</Link>
Next.js 13にリンクをアップグレードするには、new-link
コードモッドを使用できます。
<Script>
コンポーネント
next/script
の動作が更新され、pages
とapp
の両方をサポートするようになりましたが、スムーズな移行を確保するためにいくつかの変更が必要です:
- 以前に
_document.js
に含めていたbeforeInteractive
スクリプトをルートレイアウトファイル(app/layout.tsx
)に移動します。 - 実験的な
worker
戦略は現在app
では機能せず、この戦略で指定されたスクリプトは削除するか、別の戦略(例:lazyOnload
)を使用するように変更する必要があります。 onLoad
、onReady
、onError
ハンドラーはServer Componentsでは機能しないため、Client Componentに移動するか、完全に削除する必要があります。
フォント最適化
以前、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への移行は、Server Components、Suspense、およびその他のReact機能をNext.jsが活用する初めての機会かもしれません。特殊ファイルやレイアウトなどのNext.jsの新機能と組み合わせると、移行には新しい概念、メンタルモデル、および動作の変化を学ぶ必要があります。
これらの更新の複雑さを軽減するために、移行を小さなステップに分割することをお勧めします。app
ディレクトリはpages
ディレクトリと同時に動作するように意図的に設計されており、ページごとの段階的な移行が可能です。
app
ディレクトリはネストされたルートとレイアウトをサポートします。詳細はこちら。- ネストされたフォルダを使用してルートを定義し、特殊な
page.js
ファイルを使用してルートセグメントを公開アクセス可能にします。詳細はこちら。 - 特殊ファイル規則を使用して、各ルートセグメントのUIを作成します。最も一般的な特殊ファイルは
page.js
とlayout.js
です。page.js
を使用して、ルートに固有のUIを定義します。layout.js
を使用して、複数のルート間で共有されるUIを定義します。- 特殊ファイルには
.js
、.jsx
、または.tsx
ファイル拡張子を使用できます。
- コンポーネント、スタイル、テストなどの他のファイルを
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({
// レイアウトはchildren propを受け取る必要があります
// これはネストされたレイアウトやページで埋められます
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
app
ディレクトリには必ずルートレイアウトを含める必要があります。- ルートレイアウトは
<html>
と<body>
タグを定義する必要があります。Next.jsは自動的にこれらを作成しません。 - ルートレイアウトは
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/*
には適用されません。移行中は_app
/_document
を維持して、pages/*
ルートが壊れないようにする必要があります。完全に移行してから、安全に削除できます。
React Contextプロバイダーを使用している場合は、Client Componentに移動する必要があります。
getLayout()
パターンからレイアウトへの移行(任意)
Next.jsでは、pages
ディレクトリでページごとのレイアウトを実現するためにページコンポーネントにプロパティを追加することを推奨していました。このパターンは、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
の内容を新しいClient Componentに移動して、pages
ディレクトリの動作を維持します。app/dashboard/DashboardLayout.js'use client' // このディレクティブはファイルの先頭にあるべきで、インポートの前に配置します。 // これはClient Componentです export default function DashboardLayout({ children }) { return ( <div> <h2>My Dashboard</h2> {children} </div> ) }
-
DashboardLayout
をapp
ディレクトリ内の新しいlayout.js
ファイルにインポートします。app/dashboard/layout.jsimport DashboardLayout from './DashboardLayout' // これはServer Componentです export default function Layout({ children }) { return <DashboardLayout>{children}</DashboardLayout> }
-
クライアントに送信するコンポーネントJavaScriptの量を減らすために、
DashboardLayout.js
(Client Component)の非インタラクティブな部分をlayout.js
(Server Component)に段階的に移動できます。
ステップ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
ディレクトリのページはデフォルトでServer Componentsです。これは、ページがClient Componentsであるpages
ディレクトリとは異なります。- データ取得は
app
で変更されました。getServerSideProps
、getStaticProps
、getInitialProps
はよりシンプルなAPIに置き換えられました。 app
ディレクトリはネストされたフォルダを使用してルートを定義し、特殊なpage.js
ファイルを使用してルートセグメントを公開アクセス可能にします。-
pages
ディレクトリapp
ディレクトリルート index.js
page.js
/
about.js
about/page.js
/about
blog/[slug].js
blog/[slug]/page.js
/blog/post-1
ページの移行を主に2つのステップに分けることをお勧めします:
- ステップ1:デフォルトエクスポートされたPageコンポーネントを新しいClient Componentに移動します。
- ステップ2:新しいClient Componentを
app
ディレクトリ内の新しいpage.js
ファイルにインポートします。
補足: これは
pages
ディレクトリと最も比較可能な動作を持つため、最も簡単な移行パスです。
ステップ1:新しいClient Componentを作成する
app
ディレクトリ内に新しい別ファイル(例:app/home-page.tsx
など)を作成し、Client Componentをエクスポートします。Client Componentを定義するには、ファイルの先頭(インポートの前)に'use client'
ディレクティブを追加します。- Pages Routerと同様に、初回ページ読み込み時にClient Componentを静的HTMLに事前レンダリングする最適化ステップがあります。
pages/index.js
からデフォルトエクスポートされたページコンポーネントをapp/home-page.tsx
に移動します。
'use client'
// これはClient Componentです(`pages`ディレクトリのコンポーネントと同じ)
// propsとしてデータを受け取り、状態とエフェクトにアクセスでき、
// 初回ページ読み込み時にサーバー上で事前レンダリングされます。
export default function HomePage({ recentPosts }) {
return (
<div>
{recentPosts.map((post) => (
<div key={post.id}>{post.title}</div>
))}
</div>
)
}
ステップ2:新しいページを作成する
-
app
ディレクトリ内に新しいapp/page.tsx
ファイルを作成します。これはデフォルトでServer Componentです。 -
home-page.tsx
Client Componentをページにインポートします。 -
pages/index.js
でデータを取得していた場合は、新しいデータ取得APIを使用して、データ取得ロジックをServer Componentに直接移動します。詳細についてはデータ取得アップグレードガイドを参照してください。app/page.tsxTypeScript// 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() { // Server Componentで直接データを取得 const recentPosts = await getPosts() // 取得したデータをClient Componentに転送 return <HomePage recentPosts={recentPosts} /> }
-
以前のページで
useRouter
を使用していた場合は、新しいルーティングフックに更新する必要があります。詳細はこちら。 -
開発サーバーを起動し、
http://localhost:3000
にアクセスします。既存のインデックスルートが表示されるはずですが、今度はapp
ディレクトリを通じて提供されています。
ステップ5:ルーティングフックの移行
app
ディレクトリでの新しい動作をサポートするために、新しいルーターが追加されました。
app
では、next/navigation
からインポートされる3つの新しいフック、useRouter()
、usePathname()
、およびuseSearchParams()
を使用する必要があります。
- 新しい
useRouter
フックはnext/navigation
からインポートされ、next/router
からインポートされるpages
のuseRouter
フックとは異なる動作をします。next/router
からインポートされるuseRouter
フックはapp
ディレクトリではサポートされていませんが、pages
ディレクトリでは引き続き使用できます。
- 新しい
useRouter
はpathname
文字列を返しません。代わりに別のusePathname
フックを使用してください。 - 新しい
useRouter
はquery
オブジェクトを返しません。検索パラメータと動的ルートパラメータは現在別々になっています。代わりにuseSearchParams
とuseParams
フックを使用してください。 useSearchParams
とusePathname
を一緒に使用して、ページの変更をリッスンできます。詳細についてはRouter Eventsセクションを参照してください。- これらの新しいフックはClient Componentsでのみサポートされています。Server Componentsでは使用できません。
'use client'
import { useRouter, usePathname, useSearchParams } from 'next/navigation'
export default function ExampleClientComponent() {
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()
// ...
}
さらに、新しいuseRouter
フックには以下の変更があります:
isFallback
は、fallback
が置き換えられたため削除されました。locale
、locales
、defaultLocales
、domainLocales
の値は、app
ディレクトリでは組み込みのi18n Next.js機能が不要になったため削除されました。i18nについて詳しく学ぶ。basePath
は削除されました。代替手段はuseRouter
の一部ではありません。まだ実装されていません。asPath
は、新しいルーターからas
の概念が削除されたため削除されました。isReady
は不要になったため削除されました。静的レンダリング中にuseSearchParams()
フックを使用するコンポーネントは、事前レンダリングステップをスキップし、代わりに実行時にクライアント上でレンダリングされます。route
は削除されました。usePathname
またはuseSelectedLayoutSegments()
が代替手段を提供します。
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() {
// このリクエストは手動で無効化されるまでキャッシュされます。
// `getStaticProps`と同様です。
// `force-cache`はデフォルトであり、省略できます。
const staticData = await fetch(`https://...`, { cache: 'force-cache' })
// このリクエストはすべてのリクエストで再取得されます。
// `getServerSideProps`と同様です。
const dynamicData = await fetch(`https://...`, { cache: 'no-store' })
// このリクエストは10秒の寿命でキャッシュされます。
// `revalidate`オプション付きの`getStaticProps`と同様です。
const revalidatedData = await fetch(`https://...`, {
next: { revalidate: 10 },
})
return <div>...</div>
}
サーバーサイドレンダリング(getServerSideProps
)
pages
ディレクトリでは、getServerSideProps
はサーバー上でデータを取得し、ファイル内のデフォルトエクスポートされたReactコンポーネントにプロップを転送するために使用されます。ページの初期HTMLはサーバーから事前レンダリングされ、その後ブラウザで「ハイドレーション」(インタラクティブにする)されます。
// `pages`ディレクトリ
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では、Server Componentsを使用してReactコンポーネント内でデータ取得をコロケーションできます。これにより、サーバーからのレンダリングされたHTMLを維持しながら、クライアントに送信するJavaScriptを減らすことができます。
cache
オプションをno-store
に設定することで、取得したデータをキャッシュしないように指示できます。これはpages
ディレクトリのgetServerSideProps
と同様です。
// `app`ディレクトリ
// この関数は任意の名前を付けることができます
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`ディレクトリ
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に基づいており、Server Components内でリクエストヘッダーを取得するために使用できます。cookies
:Web Cookies APIに基づいており、Server Components内でクッキーを取得するために使用できます。
// `app`ディレクトリ
import { cookies, headers } from 'next/headers'
async function getData() {
const authHeader = (await headers()).get('authorization')
return '...'
}
export default async function Page() {
// Server Components内で直接または
// データ取得関数内で`cookies`または`headers`を使用できます
const theme = (await cookies()).get('theme')
const data = await getData()
return '...'
}
静的サイト生成(getStaticProps
)
pages
ディレクトリでは、getStaticProps
関数を使用してビルド時にページを事前レンダリングします。この関数を使用して外部APIやデータベースから直接データを取得し、ビルド中にページが生成されるときにこのデータをページ全体に渡すことができます。
// `pages`ディレクトリ
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`ディレクトリ
// この関数は任意の名前を付けることができます
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`ディレクトリ
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`ディレクトリ
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} />
}
generateStaticParams
という名前を使用することは、app
ディレクトリの新しいモデルにとってgetStaticPaths
よりも適切です。get
プレフィックスは、getStaticProps
とgetServerSideProps
がもはや必要ないため、より説明的なgenerate
に置き換えられました。Paths
サフィックスは、複数の動的セグメントを持つネストされたルーティングにより適切なParams
に置き換えられました。
fallback
の置き換え
pages
ディレクトリでは、getStaticPaths
から返されるfallback
プロパティは、ビルド時に事前レンダリングされないページの動作を定義するために使用されます。このプロパティは、ページが生成されている間にフォールバックページを表示するtrue
、404ページを表示するfalse
、またはリクエスト時にページを生成するblocking
に設定できます。
// `pages`ディレクトリ
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'
オプションを置き換えます。ストリーミングでは'blocking'
とtrue
の違いは無視できるため、dynamicParams
にはfallback: 'blocking'
オプションは含まれていません。
// `app`ディレクトリ
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
(デフォルト)に設定すると、生成されていないルートセグメントが要求された場合、サーバーレンダリングされてキャッシュされます。
インクリメンタル静的再生成(revalidate
付きのgetStaticProps
)
pages
ディレクトリでは、getStaticProps
関数にrevalidate
フィールドを追加して、一定時間後にページを自動的に再生成することができます。
// `pages`ディレクトリ
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`ディレクトリ
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ルートを使用していた場合は、代わりにServer Componentsを使用してデータを安全に取得できるようになりました。データ取得についての詳細をご覧ください。
シングルページアプリケーション
同時にシングルページアプリケーション(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}', // <-- この行を追加
'./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間のナビゲーションを最適化して、プリフェッチされた高速なページ遷移を維持できます。詳細はこちら。
コードモッド
Next.jsは、機能が非推奨になったときにコードベースのアップグレードを支援するためのCodemod変換を提供しています。詳細についてはコードモッドを参照してください。