March 27, 2020
Gatsby, Contentful, Netlifyで多言語ブログを作る方法 #3 - ブログ記事ページ
静的サイトジェネレーターGatsbyで作ったブログを多言語化する方法を解説。Part 3ではブログ記事ページを作成し、トップページからその記事へリンクをはります。
Updated at November 06, 2020
Part3では、ブログ記事ページを作っていきます💪
ブログ記事ページを作成
blog-post.jsテンプレートを作成
まずは /src/templates/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()
を追記し、ビルド時に記事ページを生成します。
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を渡す
},
})
})
})
}
ここでポイントは、pageContext
に slug
としてContentfulから取得したPathを渡すところです。
では、ここまでで gatsby develop
してみましょう。
URLを直接入力してみます。私の場合は http://localhost:8000/my-first-post 。
ブログ記事ページの枠ができましたね😀
では、ここにContentfulで入力した記事の内容が入るようにしていきます。
タイトルを表示
まずは、GraphQLでクエリをチェック。
path
と node_locale
でフィルターをかけると、特定のブログ記事データのみ取得できてますね。
次は、ブラウザのデベロッパーツールで BlogPost
コンポーネントを見ると、 pageContext
に slug: "my-first-post"
があるのが確認できます。
この slug
は、先ほどgatsby-node.jsに設定したものです。この slug
を使って、クエリ内で取得するブログ記事にフィルターをかけます。
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
とりあえず、ブログ記事のタイトルだけ表示するようにしてみました。
コンテンツを表示
マークダウンを取得して表示
まずはGraphQLをチェック。
content
にマークダウンで入力した内容が取得できています。それをそのまま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
そう!マークダウンがそのまま表示されちゃう。
gatsby-transformer-remarkを使おう
ということで、gatsby-transformer-remark というプラグインを使い、マークダウンをhtmlにコンバートする必要があります。
gatsby-transformer-remarkをインストール。
npm install --save gatsby-transformer-remark
そして、 gatsby-config.jsにプラグインを追記。
plugins: [
`gatsby-transformer-remark`
]
ここで改めてGraphQLをチェック。
childMarkdownRemark
に html
が!
あとは、このhtmlを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
}
}
}
}
`
ブラウザで確認すると、こんな感じ。
完璧👏
トップページにリンクを追加
あともう少しです!
トップページのブログ記事一覧から、ブログ記事ページへ遷移するようにリンクを貼ります。
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
これで完成です🙌
Part3はここまで!Part4では、ローカルで作ったブログをNetlifyでデプロイしていきます。
👋ちなみに、ここまでのコードはGitHubでも確認できます。パートごとにブランチを分けているので、よかったら参考にしてみてください😉