Gatsbyの驚くべきパフォーマンスにもかかわらず、ユーザーにすべての投稿を同じページにロードするように強制しないのが最善です。 代わりに、 gatsby-awesome-pagination プラグインを調べて、投稿アーカイブをより管理しやすいセクションに分割します。

インストール

マークダウンサポートが付属しているので、gatsby-starter-blogスターターから始めます。

$ gatsby new pagination-example https://github.com/gatsbyjs/gatsby-starter-blog
$ yarn add gatsby-awesome-pagination

ページ付け

gatsby-node.jsファイルで、paginateメソッドをインポートし、投稿のクエリの下にオブジェクトを渡します。 必要なのは、createPageアクション、投稿の配列、ページあたりのアイテム制限、新しいアーカイブページのスラッグ、およびそのテンプレートです。 このクエリを実行すると、レンダリングされるページを管理するために使用するpageContextプロップにたくさんの追加情報が表示されます。

gatsby-node.js
const { paginate } = require('gatsby-awesome-pagination');

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions

  const blogPost = path.resolve(`./src/templates/blog-post.js`)
  const result = await graphql(` ... `)

  paginate({
    createPage,
    items: result.data.allMarkdownRemark.edges,
    itemsPerPage: 3,
    pathPrefix: '/posts',
    component: path.resolve('src/templates/blog-archive.js')
  });
};

レンプレート

gatsby-awesome-paginationプラグインは、私が知る限り、個別の「アーカイブ」ページをページ付けするためのものです。 したがって、スターターのホームページにページ付けを追加する代わりに、すべてを含む別の投稿ページにリンクします。 通常のページの投稿のグループは、静的なクエリと、表示内容を管理するためのカルーセルのようなものを使用するのがおそらく最適です。

index.js
import React from "react";
import { Link, graphql } from "gatsby";
import Bio from "../components/bio";
import Layout from "../components/layout";

class BlogIndex extends React.Component {
  render() {
    const { data } = this.props;

    return (
      <Layout location={this.props.location}>
        <Bio />
        <Link to='/posts'><button>See All Posts</button></Link>
      </Layout>
    )
  }
};

export default BlogIndex;

アーカイブテンプレートは、その小道具でクエリのpageContextにすでにアクセスできます。これは、別のPagerコンポーネントに渡されます。 pageContextskipおよびlimit引数に値を渡すため、静的クエリの代わりに通常のクエリを使用する必要があることに注意してください。セットする。

blog-archive.js
import Pager from '../components/pager';

export const pageQuery = graphql`
  query($skip: Int!, $limit: Int!) {
    site { ... }
    allMarkdownRemark(
        sort: { fields: [frontmatter___date], order: DESC},
        skip: $skip,
        limit: $limit
        ) {
      edges { ... }
    }
  }
`;

const BlogArchive = ({ data, pageContext, location }) => {
    const posts = data.allMarkdownRemark.edges;

    return (
      <Layout location={location}>
        {posts.map(({ node }) => {
            const title = node.frontmatter.title || node.fields.slug
            return (
              <article key={node.fields.slug}>
                <header>
                  <h3>
                    <Link to={node.fields.slug}> {title} </Link>
                  </h3>
                  <small>{node.frontmatter.date}</small>
                </header>
                <section>
                  <p dangerouslySetInnerHTML={{ __html: node.frontmatter.description || node.excerpt }} />
                </section>
              </article>
            )
        })}

        <Pager pageContext={pageContext} />
      </Layout>
    )
};

export default BlogArchive;

ページャ

最後のステップは、pageContextからページパスを取得するのと同じくらい簡単です。 pageContextをログに記録すると、クエリに渡されているskipおよびlimitプロパティと、pageNumberおよびnumberOfPagesが表示されます。 ]これを使用して、各ページの番号とリンクを生成できます。

components / pager.js
import React from 'react';
import { Link } from 'gatsby';

const Pager = ({ pageContext }) => {
  console.log(pageContext);
  const { previousPagePath, nextPagePath } = pageContext;
  return (
    <nav style={{ display: 'flex', justifyContent: 'space-between' }}>
      <div>
        {previousPagePath && (
          <Link to={previousPagePath}>
            <button>← Newer Posts</button>
          </Link>
        )}
      </div>

      <div style={{ justifySelf: 'flex-end' }}>
        {nextPagePath && (
          <Link to={nextPagePath}>
            <button>Older Posts →</button>
          </Link>
        )}
      </div>
    </nav>
  );
};

export default Pager;

投稿

各投稿間にナビゲーションを追加するのも同じくらい簡単で、プラグインも必要ありません。 この特定のスターターは実際にはすでにこれをサポートしていますが、今のところサポートしていないふりをしましょう。

クエリからページを作成する場合、pageContextでアクセスできる2つのフィールドを追加する必要があります。 それが最初の投稿である場合、prevは存在しないはずです。そうでない場合は、最後の投稿を返します。 nextと同じように、次の投稿が存在する場合にのみ返されます。

gatsby-node.js
posts.forEach((post, index) => {
  createPage({
    path: post.node.fields.slug,
    component: blogPost,
    context: {
      slug: post.node.fields.slug,
      prev: index === 0 ? null : posts[index - 1].node,
      next: index === (posts.length - 1) ? null : posts[index + 1].node
    },
  })
});

これは、Pagerの場合と同じ実行であり、prev / nextが存在するかどうかを確認し、Linkにスローすると、完了です。

blog-post.js
const BlogPostTemplate = ({ data, pageContext, location }) => {
  const post = data.markdownRemark;
  const { prev, next } = pageContext;

  return (
    <Layout location={location}>
      <Link to='/posts'>Archive</Link>
      <article>
        <header>
          <h1> {post.frontmatter.title} </h1>
          <p> {post.frontmatter.date} </p>
        </header>
        <section dangerouslySetInnerHTML={{ __html: post.html }} />
        <hr />
      </article>

      <nav style={{ display: 'flex', justifyContent: 'space-between' }}>
        <div>
          {prev && <Link to={prev.fields.slug} rel="prev"> ← Last Post </Link>}
        </div>

        <div style={{ justifySelf: 'flex-end' }}>
          {next && <Link to={next.fields.slug} rel="next"> Next Post → </Link>}
        </div>
      </nav>
    </Layout>
  )
};

export default BlogPostTemplate;

まとめ

このプラグインはまだ解決されていませんが、このすでに信じられないほどシンプルなデザインがどのように改善されるかを楽しみにしています。