March 27, 2020

Gatsby, Contentful, Netlifyで多言語ブログを作る方法 #3 - ブログ記事ページ

静的サイトジェネレーターGatsbyで作ったブログを多言語化する方法を解説。Part 3ではブログ記事ページを作成し、トップページからその記事へリンクをはります。

Updated at November 06, 2020

Part3では、ブログ記事ページを作っていきます💪

  1. GatsbyサイトにContentfulのデータを読み込む
  2. 多言語化する
  3. ブログ記事ページを作成する
  4. Netlifyでデプロイして公開する

ブログ記事ページを作成

blog-post.jsテンプレートを作成

まずは /src/templates/blog-post.js ファイルを追加。これはブログ記事を表示するためのテンプレートになります。

blog-post.js
import React from 'react'
import Layout from '../components/layout'

const BlogPost = () => (
  <Layout>
    <h1>ここにブログ記事が表示されます</h1>
  </Layout>
)

export default BlogPost

gatsby-node.jsにcreatePage()を追記

gatsby-node.jsに createPages() を追記し、ビルド時に記事ページを生成します。

gatsby-node.js
const path = require(`path`)

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

  // 追加したブログ記事テンプレート
  const blogPostTemplate = path.resolve(`src/templates/blog-post.js`)

  return graphql(
      `
        query MyQuery {
          allContentfulBlog {
            edges {
              node {
                path
              }
            }
          }
        }
      `
  ).then(result => {
      if(result.errors) {
          throw result.errors
      }

      // ブログ記事ページを生成
      result.data.allContentfulBlog.edges.forEach(edge => {
          const path = edge.node.path
          createPage({
              path: path,
              component: blogPostTemplate, // 追加したブログ記事テンプレート
              context: {
                slug: path, // slugとしてContentfulから取得したPathを渡す
              },
          })
      })
  })
}

ここでポイントは、pageContextslug としてContentfulから取得したPathを渡すところです。

では、ここまでで gatsby develop してみましょう。

URLを直接入力してみます。私の場合は http://localhost:8000/my-first-post 。

Create blog post template

ブログ記事ページの枠ができましたね😀
では、ここにContentfulで入力した記事の内容が入るようにしていきます。


タイトルを表示

まずは、GraphQLでクエリをチェック。
pathnode_locale でフィルターをかけると、特定のブログ記事データのみ取得できてますね。

GraphiQL filter

次は、ブラウザのデベロッパーツールで BlogPost コンポーネントを見ると、 pageContextslug: "my-first-post" があるのが確認できます。

pageContext slug path

この slug は、先ほどgatsby-node.jsに設定したものです。この slug を使って、クエリ内で取得するブログ記事にフィルターをかけます。

blog-post.js
import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/layout'

const BlogPost = ({ data }) => (
  <Layout>
    <h1>{data.contentfulBlog.title}</h1>
  </Layout>
)

export const query = graphql`
  query BlogPostQuery($slug: String, $language: String) {
    contentfulBlog(path: { eq: $slug }, node_locale: { eq: $language }) {
      path
      node_locale
      title
    }
  }
`

export default BlogPost

とりあえず、ブログ記事のタイトルだけ表示するようにしてみました。

Display blog post title


コンテンツを表示

マークダウンを取得して表示

まずはGraphQLをチェック。

GraphiQL content

content にマークダウンで入力した内容が取得できています。それをそのままblog-post.jsに追加してみると…。

blog-post.js
import React from 'react'
import { graphql } from 'gatsby'
import Layout from '../components/layout'

const BlogPost = ({ data }) => (
  <Layout>
    <h1>{data.contentfulBlog.title}</h1>
    <div>
      {data.contentfulBlog.content.content}
    </div>
  </Layout>
)

export const query = graphql`
  query BlogPostQuery($slug: String, $language: String) {
    contentfulBlog(path: { eq: $slug }, node_locale: { eq: $language }) {
      path
      node_locale
      title
      content{
        content
      }
    }
  }
`

export default BlogPost

markdown content

そう!マークダウンがそのまま表示されちゃう。

gatsby-transformer-remarkを使おう

ということで、gatsby-transformer-remark というプラグインを使い、マークダウンをhtmlにコンバートする必要があります。

gatsby-transformer-remarkをインストール。

コマンドライン
npm install --save gatsby-transformer-remark

そして、 gatsby-config.jsにプラグインを追記。

gatsby-config.js
plugins: [
  `gatsby-transformer-remark`
]

ここで改めてGraphQLをチェック。

GraphiQL child markdown remark

childMarkdownRemarkhtml が!

あとは、このhtmlをblog-post.jsテンプレート側で表示するだけですね。

blog-post.js
const BlogPost = ({ data }) => (
  <Layout>
    <h1>{data.contentfulBlog.title}</h1>
    <div dangerouslySetInnerHTML={{ __html: data.contentfulBlog.content.childMarkdownRemark.html }} />
  </Layout>
)

export const query = graphql`
  query BlogPostQuery($slug: String, $language: String) {
    contentfulBlog(path: { eq: $slug }, node_locale: { eq: $language }) {
      path
      node_locale
      title
      content{
        childMarkdownRemark {
          html
        }
      }
    }
  }
`

ブラウザで確認すると、こんな感じ。

Display markdown contents

完璧👏


トップページにリンクを追加

あともう少しです!

トップページのブログ記事一覧から、ブログ記事ページへ遷移するようにリンクを貼ります。

index.js
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
import { useIntl, Link } from "gatsby-plugin-intl" // Linkを追加

const IndexPage = ({ data }) => {
  const intl = useIntl()
  return(
  <Layout>
    <SEO title="Home" />
    <h1>{intl.formatMessage({ id: "hello" })}</h1>
    <h2>{intl.formatMessage({ id: "posts" })}</h2>
    <ul>
      {data.allContentfulBlog.nodes.map(post => {
        return (
          <li key={post.contentful_id}>
            {/* Linkを追加 */}
            <Link to={`/${post.path}`}>{post.title}</Link>
          </li>
        )
      })}
    </ul>
  </Layout>
)}

// クエリにもpathを追加
export const query = graphql`
  query ContentFulBlog($language: String) {
    allContentfulBlog(filter: { node_locale: { eq: $language } }) {
      nodes {
        contentful_id
        node_locale
        title
        path
      }
    }
  }
`

export default IndexPage

Link to blog page

これで完成です🙌


Part3はここまで!Part4では、ローカルで作ったブログをNetlifyでデプロイしていきます。

👋ちなみに、ここまでのコードはGitHubでも確認できます。パートごとにブランチを分けているので、よかったら参考にしてみてください😉

  1. GatsbyサイトにContentfulのデータを読み込む
  2. 多言語化する
  3. ブログ記事ページを作成する
  4. Netlifyでデプロイして公開する
高橋あゆみ

高橋あゆみ
フリーランスのUI/UXデザイナー。英語圏のロマンス・ミステリー小説にハマり、一向に減らない積読が悩み。カナダのバンクーバー在住。