コンテンツにスキップ

ページからアプリへ

このガイドでは、次のことを行います。

アップグレード

Node.jsバージョン Node.jsドキュメントを参照してください。

Next.jsバージョン

Next.jsバージョン13にアップデートするには、お好みのパッケージマネージャーを使用して次のコマンドを実行します。

ターミナル
npm install next@latest react@latest react-dom@latest

ESLintバージョン
ターミナル
npm install -D eslint-config-next@latest

知っておくと便利: ESLintの変更を有効にするには、VS CodeでESLintサーバーを再起動する必要がある場合があります。コマンドパレット (Macではcmd+shift+p、Windowsではctrl+shift+p) を開き、ESLint: ESLintサーバーの再起動を検索します。

次のステップ

アップデート後、次のステップについては、以下のセクションを参照してください。

新機能へのアップグレード

Next.js 13では、新しい機能と規約を備えた新しいApp Routerが導入されました。新しいRouterはappディレクトリで使用でき、pagesディレクトリと共存します。

Next.js 13へのアップグレードでは、新しいApp Routerを使用する必要はありません。 更新されたImageコンポーネントLinkコンポーネントScriptコンポーネントフォントの最適化など、両方のディレクトリで動作する新しい機能とともに、pagesを引き続き使用できます。

<Image/>コンポーネント next-image-to-legacy-imageコードモッドnext/imageインポートをnext/legacy/imageに安全かつ自動的に名前変更します。既存のコンポーネントは同じ動作を維持します。
  • next-image-experimentalコードモッド:インラインスタイルを危険に追加し、未使用のプロップを削除します。これは、既存のコンポーネントの動作を新しいデフォルトと一致するように変更します。このコードモッドを使用するには、最初にnext-image-to-legacy-imageコードモッドを実行する必要があります。
  • <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コードモッドを使用できます。

    <Script>コンポーネント

    next/scriptの動作は、pagesappの両方をサポートするように更新されましたが、スムーズな移行を確実にするためにいくつかの変更を行う必要があります

    • 以前に_document.jsに含めていたbeforeInteractiveスクリプトをルートレイアウトファイル(app/layout.tsx)に移動します。
    • 実験的なworker戦略はまだappでは機能せず、この戦略で示されたスクリプトは削除するか、別の戦略(例:lazyOnload)を使用するように変更する必要があります。
    • onLoadonReady、および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.jslayout.jsです。
      • page.jsを使用して、ルートに固有のUIを定義します。
      • layout.jsを使用して、複数のルートで共有されるUIを定義します。
      • .js.jsx、または.tsxファイル拡張子は、特別なファイルに使用できます。
    • コンポーネント、スタイル、テストなど、他のファイルをappディレクトリ内に配置できます。 詳細はこちら
    • getServerSidePropsgetStaticPropsなどのデータフェッチ関数は、app内の新しいAPIに置き換えられました。 getStaticPathsgenerateStaticParamsに置き換えられました。
    • pages/_app.jspages/_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内のすべてのルートに適用されるルートレイアウトです。

    app/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>
      )
    }
    • appディレクトリには、ルートレイアウトが必須です。
    • Next.jsは自動的に作成しないため、ルートレイアウトでは<html>タグと<body>タグを定義する必要があります
    • ルートレイアウトは、pages/_app.tsxファイルとpages/_document.tsxファイルを置き換えます。
    • .js.jsx、または.tsx拡張子は、レイアウトファイルに使用できます。

    <head> HTML要素を管理するには、組み込みSEOサポートを使用できます

    app/layout.tsx
    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 ディレクトリでページごとのレイアウトを実現するために、ページコンポーネントにプロパティを追加することを推奨していました。このパターンは、app ディレクトリでの ネストされたレイアウト のネイティブサポートに置き換えることができます。

    移行前後の例を参照してください

    移行前

    components/DashboardLayout.js
    export default function DashboardLayout({ children }) {
      return (
        <div>
          <h2>My Dashboard</h2>
          {children}
        </div>
      )
    }
    pages/dashboard/index.js
    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.js
      export 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>
        )
      }
    • DashboardLayoutapp ディレクトリ内の新しい layout.js ファイルにインポートします。

      app/dashboard/layout.js
      import 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 コンポーネントを使用して、titlemeta などの <head> HTML 要素を管理します。 app ディレクトリでは、next/head は新しい 組み込み SEO サポート に置き換えられます。

    移行前

    pages/index.tsx
    import Head from 'next/head'
     
    export default function Page() {
      return (
        <>
          <Head>
            <title>My page title</title>
          </Head>
        </>
      )
    }

    移行後

    app/page.tsx
    import type { Metadata } from 'next'
     
    export const metadata: Metadata = {
      title: 'My Page Title',
    }
     
    export default function Page() {
      return '...'
    }

    すべてのメタデータオプションを参照してください.

    ステップ4: ページの移行

    • app ディレクトリ のページは、デフォルトで サーバーコンポーネント です。これは、ページが クライアントコンポーネント である pages ディレクトリとは異なります。
    • app では、データフェッチ が変更されました。 getServerSidePropsgetStaticPropsgetInitialProps は、よりシンプルな API に置き換えられました。
    • app ディレクトリは、ネストされたフォルダーを使用して ルートを定義 し、特別な page.js ファイルを使用してルートセグメントを公開します。
    • pages ディレクトリapp ディレクトリルート
      index.jspage.js/
      about.jsabout/page.js/about
      blog/[slug].jsblog/[slug]/page.js/blog/post-1

    ページの移行は、主に2つのステップに分割することをお勧めします

    • ステップ1: デフォルトでエクスポートされたページコンポーネントを新しいクライアントコンポーネントに移動します。
    • ステップ2: 新しいクライアントコンポーネントを app ディレクトリ内の新しい page.js ファイルにインポートします。

    **知っておくと良いこと**: これは、pages ディレクトリと最も比較しやすい動作をするため、最も簡単な移行パスです。

    ステップ1: 新しいクライアントコンポーネントを作成する

    • app ディレクトリ内に、クライアントコンポーネントをエクスポートする新しいファイル(例:app/home-page.tsx など)を作成します。クライアントコンポーネントを定義するには、ファイルの先頭(インポートの前)に 'use client' ディレクティブを追加します。
      • Pages Router と同様に、クライアントコンポーネントを最初のページロード時に静的 HTML にプリレンダリングするための 最適化手順 があります。
    • デフォルトでエクスポートされたページコンポーネントを pages/index.js から app/home-page.tsx に移動します。
    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 からインポートされ、next/router からインポートされる pagesuseRouter フックとは異なる動作をします。
    • 新しい useRouterpathname 文字列を返しません。代わりに、別の usePathname フックを使用してください。
    • 新しい useRouterquery オブジェクトを返しません。検索パラメータと動的ルートパラメータは分離されました。代わりに、useSearchParams フックと useParams フックを使用してください。
    • useSearchParamsusePathname を一緒に使用して、ページの変更をリッスンできます。詳細は、ルーターイベント セクションを参照してください。
    • これらの新しいフックは、クライアントコンポーネントでのみサポートされています。サーバーコンポーネントでは使用できません。
    app/example-client-component.tsx
    '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 は削除されました。
    • 組み込みの i18n Next.js 機能は app ディレクトリでは不要になったため、localelocalesdefaultLocalesdomainLocales の値は削除されました。 i18n の詳細はこちら
    • basePath は削除されました。代替案は useRouter の一部にはなりません。まだ実装されていません。
    • 新しいルーターから as の概念が削除されたため、asPath は削除されました。
    • 不要になったため、isReady は削除されました。静的レンダリング 中、useSearchParams() フックを使用するコンポーネントはプリレンダリング手順をスキップし、代わりに実行時にクライアントでレンダリングされます。
    • route は削除されました。 usePathname または useSelectedLayoutSegments() が代替手段を提供します。

    useRouter() API リファレンスを表示する.

    pagesapp 間のコンポーネント共有

    pagesapp ルーター間でコンポーネントの互換性を維持するには、next/compat/router から useRouter フック を参照してください。これは pages ディレクトリの useRouter フックですが、ルーター間でコンポーネントを共有するために使用することを意図しています。 app ルーターのみで使用できるようになったら、新しい next/navigationuseRouter に更新してください。

    ステップ 6: データ取得方法の移行

    pages ディレクトリは、getServerSidePropsgetStaticProps を使用してページのデータを取得します。 app ディレクトリ内では、これらの以前のデータ取得関数は、fetch()async React サーバーコンポーネント上に構築された よりシンプルな API に置き換えられます。

    app/page.tsx
    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 コンポーネントに props を転送するために使用されます。ページの初期 HTML はサーバーからプリレンダリングされ、ブラウザでページが「ハイドレート」されます(インタラクティブになります)。

    pages/dashboard.js
    // `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 コンポーネント内にデータ取得を配置できます。これにより、サーバーからレンダリングされた HTML を維持しながら、クライアントに送信する JavaScript の量を削減できます。

    cache オプションを no-store に設定することにより、取得したデータを キャッシュしない ように指定できます。これは、pages ディレクトリの getServerSideProps と似ています。

    app/dashboard/page.tsx
    // `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 オブジェクトを取得し、それを使用してリクエストの Cookie とヘッダーを取得できます。

    pages/index.js
    // `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 ディレクトリは、リクエストデータを取得するための新しい読み取り専用関数を公開しています

    app/page.tsx
    // `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/index.js
    // `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/page.js
    // `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/posts/[id].js
    // `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/posts/[id]/page.js
    // `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/${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` 接頭辞は、より記述的な `generate` に置き換えられました。これは、`getStaticProps` と `getServerSideProps` が不要になったため、単独でより適切に配置されます。 `Paths` 接尾辞は `Params` に置き換えられました。これは、複数の動的セグメントを持つネストされたルーティングに適しています。


    `fallback` の置き換え

    `pages` ディレクトリでは、`getStaticPaths` から返される `fallback` プロパティを使用して、ビルド時にプリレンダリングされないページの動作を定義します。このプロパティは、ページの生成中にフォールバックページを表示するには `true` に、404 ページを表示するには `false` に、リクエスト時にページを生成するには `blocking` に設定できます。

    pages/posts/[id].js
    // `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'` オプションを置き換えます。ストリーミングを使用すると `'blocking'` と `true` の違いは無視できるため、`fallback: 'blocking'` オプションは `dynamicParams` に含まれていません。

    app/posts/[id]/page.js
    // `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` (デフォルト) に設定すると、生成されていないルートセグメントがリクエストされた場合、サーバーレンダリングされてキャッシュされます。

    増分静的再生成 ( `revalidate` を使用した `getStaticProps` )
    pages/index.js
    // `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/page.js
    // `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 リクエスト および レスポンス API を使用して、特定のルートのカスタムリクエストハンドラを作成できます。

    app/api/route.ts
    export async function GET(request: Request) {}

    **知っておくと役立つ情報**: 以前は API ルートを使用してクライアントから外部 API を呼び出していた場合、代わりに サーバーコンポーネント を使用して安全にデータを取得できるようになりました。 データフェッチ の詳細をご覧ください。

    ステップ 7: スタイル設定

    `pages` ディレクトリでは、グローバルスタイルシートは `pages/_app.js` に制限されています。 `app` ディレクトリでは、この制限が解除されました。グローバルスタイルは、任意のレイアウト、ページ、またはコンポーネントに追加できます。

    Tailwind CSS

    Tailwind CSSを使用している場合は、appディレクトリをtailwind.config.jsファイルに追加する必要があります。

    tailwind.config.js
    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ファイルにインポートする必要があります。

    app/layout.js
    import '../styles/globals.css'
     
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>{children}</body>
        </html>
      )
    }

    Tailwind CSSを使ったスタイリングについてもっと詳しく知る

    コードモッド

    Next.jsは、機能が非推奨になった場合にコードベースのアップグレードを支援するためのコードモッド変換を提供しています。詳細については、コードモッドを参照してください。