Gatsby.js スタティックサイトのチュートリアル Part 8
Gatsby.jsでMDXを使用したブログサイトを作成するチュートリアルのPart8です。今回はgatsby-plugin-imageのGatsbyImageコンポーネントを使用して、各ブログポストにヒーローイメージを追加して、ブログページのリストにも表示できるようにしていきます。
GatsbyImageコンポーネント
このチュートリアルのPart3でホームページに画像を表示した際はStaticImageコンポーネントで画像を表示しましたが、動的ルーティングで作成されたブログポストのページにpropsとしてイメージを受け渡す場合にはGatsbyImageコンポーネントを使用する必要があります。
ブログポストにヒーローイメージを追加する
まずblogディレクトリの構成を変更する必要があります。いまはblogフォルダの直下に各記事のMDXファイルが置かれている状態です。
これを各ブログポストごとにサブディレクトリを作成し、各MDXファイルをindex.mdxにリネームします。
なおフォルダ構成を変更した際はローカルサーバーの再起動が必要です。ヒーローイメージに使用する任意の画像を各ブログポストのフォルダに格納します。
各ブログポストのfrontmatterにヒーローイメージのpathとaltテキストを追記します。
blog/first-post/index.mdx frontmatter
---
title: "First Post"
date: "2024-04-01"
slug: "first-post"
hero_image: "./sample-image-1.png"
hero_image_alt: "Alt text for your image"
---
blog/second-post/index.mdx frontmatter
---
title: "Second Post"
date: "2024-04-02"
slug: "second-post"
hero_image: "./sample-image-2.png"
hero_image_alt: "Alt text for your image"
---
blog/third-post/index.mdx frontmatter
---
title: "Third Post"
date: "2024-04-03"
slug: "third-post"
hero_image: "./sample-image-3.png"
hero_image_alt: "Alt text for your image"
---
blog/fourth-post/index.mdx frontmatter
---
title: "Fourth Post"
date: "2024-04-04"
slug: "fourth-post"
hero_image: "./sample-image-4.png"
hero_image_alt: "Alt text for your image"
---
blog/fifth-post/index.mdx frontmatter
---
title: "Fifth Post"
date: "2024-04-05"
slug: "fifth-post"
hero_image: "./sample-image-5.png"
hero_image_alt: "Alt text for your image"
---
blog/sixth-post/index.mdx frontmatter
---
title: "Sixth Post"
date: "2024-04-06"
slug: "sixth-post"
hero_image: "./sample-image-6.png"
hero_image_alt: "Alt text for your image"
---
gatsby-transformer-sharpプラグインで画像を変換する
GatsbyImageコンポーネントを使用するためにgatsby-transformer-sharpプラグインをインストールします。このプラグインを使用すると画像ファイル(.pngや.jpgといった拡張子のフ ァイル)をImageSharpノードに変換しGraphQLで取得できるようにしてくれます。CLIで下記コマンドを実行します。
npm install gatsby-transformer-sharp
gatsby-transformer-sharpをgatsby-config.jsに追記します。
gatsby-config.js
module.exports = {
siteMetadata: {
title: `Gatsby Static Site Tutorial`,
},
plugins: [
`gatsby-plugin-image`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `blog`,
path: `${__dirname}/blog`,
}
},
`gatsby-plugin-mdx`,
`gatsby-transformer-sharp`,
],
};
gatsby-config.jsを変更したのでローカルサーバーを再起動しておきましょう。
ブログポストにヒーローイメージを表示する
画像と必要なツールが準備できたので{mdx.frontmatter__slug}.jsにGatsbyImageコンポーネントを追加します。まずGraphiQLでクエリを作成します。frontmatterのhero_image_altとhero_image内の childImageSharp → gatsbyImageData を追加で選択すればOKです。
クエリは下記のようになります。
GraphQL
query ($id: String) {
mdx(id: {eq: $id}) {
frontmatter {
title
date(formatString: "MMMM D, YYYY")
hero_image_alt
hero_image {
childImageSharp {
gatsbyImageData
}
}
}
}
}
クエリを作成できたので{mdx.frontmatter__slug}.jsを下記のように変更します。
src/pages/blog/{mdx.frontmatter__slug}.js
import * as React from 'react'
import { graphql } from 'gatsby'
import { GatsbyImage, getImage } from 'gatsby-plugin-image'
import Layout from '../../components/layout'
import Seo from '../../components/seo'
const BlogPost = ({ data, children }) => {
const image = getImage(data.mdx.frontmatter.hero_image)
return (
<Layout pageTitle={data.mdx.frontmatter.title}>
<p>{data.mdx.frontmatter.date}</p>
<GatsbyImage
image={image}
alt={data.mdx.frontmatter.hero_image_alt}
/>
{children}
</Layout>
)
}
export const query = graphql`
query ($id: String) {
mdx(id: {eq: $id}) {
frontmatter {
title
date(formatString: "MMMM D, YYYY")
hero_image_alt
hero_image {
childImageSharp {
gatsbyImageData
}
}
}
}
}
`
export const Head = ({ data }) => <Seo title={data.mdx.frontmatter.title} />
export default BlogPost
gatsby-plugin-imageプラグインからGatsbyImageとgetImageを読み込みます。getImageはGatsbyImageから画像を取得する際に使用するヘルパーファンクションです。これで各ブログポストのページにヒーローイメージが追加できました。
ブログページにブログポストのヒーローイメージを表示する
ブログの一覧ページでも画像を表示できるようにします。GraphiQLで下記のようにクエリを作成します。
GraphQL
query MyQuery {
allMdx(sort: {frontmatter: {date: DESC}}) {
nodes {
frontmatter {
title
date(formatString: "MMMM D, YYYY")
slug
hero_image_alt
hero_image {
childImageSharp {
gatsbyImageData
}
}
}
id
excerpt
}
}
}
hero_imageとhero_image_altを追加しています。ブログページを下記のように変更します。
src/pages/blog/index.js
import * as React from 'react'
import { Link, graphql } from 'gatsby'
import { GatsbyImage, getImage } from 'gatsby-plugin-image'
import Layout from '../../components/layout'
import Seo from '../../components/seo'
const BlogPage = ({ data }) => {
return (
<Layout pageTitle="Blog">
{
data.allMdx.nodes.map((node) => (
<article key={node.id}>
<h2>
<Link to={`/blog/${node.frontmatter.slug}`}>
{node.frontmatter.title}
</Link>
</h2>
<GatsbyImage
image={getImage(node.frontmatter.hero_image)}
alt={node.frontmatter.hero_image_alt}
/>
<p>Posted: {node.frontmatter.date}</p>
<p>{node.excerpt}</p>
</article>
))
}
</Layout>
)
}
export const query = graphql`
query {
allMdx(sort: { frontmatter: { date: DESC }}) {
nodes {
frontmatter {
title
date(formatString: "MMMM D, YYYY")
slug
hero_image_alt
hero_image {
childImageSharp {
gatsbyImageData
}
}
}
id
excerpt
}
}
}
`
export const Head = () => <Seo title="Blog" />
export default BlogPage
GatsbyImageとgetImageを読み込み、クエリを置きかえます。タイトルの下に画像を表示するようにしています。
これでブログの一覧ページにもヒーローイメージを追加できました。今回は以上です。