Next.js: Dynamic Routes, API Routes
目次

Dynamic Routes

  • Next.js は、外部データに依存するパスを持つページを静的に生成できる。

  • これは、 Next.js において dynamic URLs を可能にする。

How to Statically Generate Pages with Dynamic Routes

  1. page ディレクトリ配下に、 [ で始まり ] で終わるファイルを作る

    • ファイル名: pages/posts/[id].js => パス: /posts/{id}

    • [ で始まり ] で終わるのが動的 page

  2. pages/posts/[id].js の中に、 getStaticPaths という非同期関数を export する。

pages/posts/[id].tsx
import Layout from "../../components/layout";
import { getAllPostIds, getPostData } from "../../lib/posts";
import Head from "next/head"
import Date from '../../components//date'
import utilStyles from '../../styles/utils.module.css'
import { GetStaticProps, GetStaticPaths } from "next";

export default function Post({
  postData
}: {
  postData: {
    title: string,
    date: string,
    contentHtml: string
  }
}) {
  /* page を返す */
  // 受け取った `postData` を使って page を生成
  return (
    <Layout>
      <Head>
        <title>{postData.title}</title>
      </Head>
      <article>
        <h1 className={utilStyles.headingXl}>{postData.title}</h1>
        <div className={utilStyles.lightText}>
          <Date dateString={postData.date} />
        </div>
        <div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
      </article>
    </Layout>
  )
}

export const getStaticPaths: GetStaticPaths = async () => {
  /* ブログIDの一覧を返す
  *
  * `/posts/{id}.js` というパスで page を返すべき ID の一覧を返すよ。
  * 取得するのは単なる文字列の配列ではなく、オブジェクトの配列である必要がある。
  * 各オブジェクトには `params` キーが必要、かつ、 `id` キーを持つオブジェクトが含まれている必要がある。
  * (`[id]` をファイル名に使用しているため。でないと `getStaticPaths` がこけちゃうよ。)
  */
  const paths = getAllPostIds()
  return {
    paths,
    fallback: false
    // fallback: true
  }
}

export const getStaticProps: GetStaticProps = async ({ params }) => {
  /* ブログID に紐づく、ページの生成に必要なデータを返す
  *
  * 引数の `params` の中に `id` が入ってる
  * (この page は `/posts/{id}.js` というパスでアクセスされる)
  */
  // どこぞから id をキーにブログのデータを取得している
  const postData = await getPostData(params.id as string)
  // The value of the `props` key will be
  //  passed to the `Post` component
  return {
    props: {
      // `props` key の inside で結果を返す
      postData
    }
  }
}

実行の順番

  1. getStaticPaths()

  2. getStaticProps()

  3. Post()

他のページからリンクするとき

// href に `[]` を使い、 `as` prop に実際のパス (id) を入れてあげる
<Link href="/posts/[id]" as="/posts/ssg-ssr">
  <a>...</a>
</Link>

getStaticPaths が実行されるタイミング

  • 開発時: リクエスト毎

  • 本番時: ビルド時

Fallback

Catch-all Routes

[] の中に ... (three dots) を入れるとすべてのパスをキャッチできるようになる

  • pages/posts/[...id].js => /posts/a/posts/a/b/posts/a/b/c もマッチする。

Router

Next.js router にアクセスしたい場合は、 next/router から useRouter hook を import する

404 Pages

カスタム 404 Page を作成できる

  • pages/404.js というファイルを作れば良い

  • ビルド時に静的生成される

ライブラリ

  • remark: Markdown コンテンツのレンダリング

  • date-fns: 日付フォーマット

API Routes

  • Next.js は API Routes をサポートしている

  • Node.js 関数として APIエンドポイントを簡単に作成できる

Creating API Routes

pages/api 配下にこんな関数を作る

pages/api/hello.ts
import { NextApiRequest, NextApiResponse } from "next";

// req = request data, res = response data
export default (_: NextApiRequest, res: NextApiResponse) => {
  // http://localhost:3000/api/hello でアクセスできる
  res.status(200).json({ text: 'Hello' })
}
  • Serverless Functions (also known as Lambdas) としてデプロイできる

  • Do Not Fetch an API Route from getStaticProps or getStaticPaths

  • 良い Use Case は、入力フォームのハンドリングです

    • page にフォームを作る

    • => API Route に POSTリクエストする

    • => API Route で直接 DBに保存する

  • API Route のコードはクライアントバンドルされないので、安全にサーバーサイドコードが記述できる

Dynamic API Routes

API Routes は、通常の page と同様に動的にできる