Next.jsのSSGモードでWordPressの記事一覧と詳細を表示する

Next.jsはversion 9.3からSSGモードが用意されました。

Next-gen Static Site Generation (SSG) Support: Built-in optimized static generation through new data fetching methods.

https://nextjs.org/blog/next-9-3#next-gen-static-site-generation-ssg-support

ということで早速試します。

Setup

create-next-appでアプリを作ります。

$ npx create-next-app example-wp-app
$ cd example-wp-app

WordPressのWP APIを叩くライブラリもいれましょう。

$ yarn add wpapi

こんな感じのディレクトリ構成になります。

% tree -L 2 -I node_modules 
.
├── README.md
├── package.json
├── pages
│   └── index.js
├── public
│   ├── favicon.ico
│   └── zeit.svg
└── yarn.lock

URLを同的に作成する

[PARAM].js のようなファイルを作ることで動的なページへのルーティングができます。

$ touch pages/posts/[id].js
-> https://example.com/posts/765432 (Post ID)

$ touch pages/[slug].js
-> https://example.com/YOUR-POST-SLUG

getStaticPaths 関数でURLを動的に作っていくことができます。

$ code pages/[slug].js
import Link from 'next/link'
import WP from 'wpapi'

const wpClient = new WP({
  endpoint: 'https://YOUR_WORDPRESS_SITE/wp-json'
})

/**
 * Create posts URLs
 **/
export const getStaticPaths = async () => {
    const posts = await wpClient.posts()
    return {
        paths: posts.map(post => ({
            params: {
                slug: post.slug
            }
        })),
        fallback: false
    }
}

/**
 * Render content
 **/
export default () => {
    return (
        <div>
            <h1>Hello</h1>
            <Link href="/">Back</Link>
        </div>
    )
}

ページ内のコンテンツを getStaticPropsで動的に取得する

getStaticProps 関数でURLのパラメタなどが拾えます。

下のサンプルではhttps://example.com/YOUR-SLUGYOUR-SLUG部分を拾っています。


export const getStaticProps = async ({params}) => {
    const posts = await wpClient.posts().slug(params.slug as string)
    return {
        props: {
            post: posts[0]
        }
    }
}

記事一覧を作る

最後にpages/index.js を開いて記事一覧を表示させましょう。

import Head from 'next/head'
import Link from 'next/link'
import WP from 'wpapi'

const wpClient = new WP({
  endpoint: 'https://YOUR_WORDPRESS_SITE/wp-json'
})

const Home = (props) => {
  return (
  <div className="container">
    <Head>
      <title>Create Next App</title>
      <link rel="icon" href="/favicon.ico" />
    </Head>

    <main>
      <h1 className="title">
        Welcome to <a href="https://nextjs.org">Next.js!</a>
      </h1>
      <ul>
        {props.posts.map(post => (
          <li key={post.id}>
            <Link href={post.slug}>
              {post.slug}
            </Link>
          </li>
        ))}
      </ul>
    </main>
  </div>
)
    }

export const getStaticProps: GetStaticProps = async () => {
  const data = await wpClient.posts()
  return {
    props: {
      posts: data
    }
  }
}

export default Home

Appendix: full example of pages/[slug].js

import Link from 'next/link'
import WP from 'wpapi'

const wpClient = new WP({
  endpoint: 'https://YOUR_WORDPRESS_SITE/wp-json'
})

export const getStaticPaths = async () => {
    const posts = await wpClient.posts()
    return {
        paths: posts.map(post => ({
            params: {
                slug: post.slug
            }
        })),
        fallback: false
    }
}

export const getStaticProps = async ({params}) => {
    const posts = await wpClient.posts().slug(params.slug as string)
    return {
        props: {
            post: posts[0]
        }
    }
}

export default ({post}) => {
    return (
        <div>
            <h1>Hello</h1>
            <h2>{post.title.rendered}</h2>
            {post.slug}
            <Link href="/">Back</Link>
        </div>
    )
}

Comment