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

Next.jsはversion 9.3からSSGモードが用意されました。 Next-gen Static Site Generation (SSG) Support: Built-in optimized static […]

広告ここから
広告ここまで

目次

    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>
        )
    }

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark