tech.sinayaka.com

GatsbyJSのスターターの編集

2024-02-08
2026-07-08
7分
1344語
GatsbyJS Gatsby
目次

    スターターから始めたGatsbyJSがいうことを聞いてくれない!やりたいことができない! そう悩んでいた時期が私にもありました・・・ しかしながら、ぶつかり稽古を繰り返すうちに少しずつではありますが、理解は進むものです。

    悩みはだいたい見た目に関すること

    「タグのstyleをチョットいじりたいだけなんだけどなあ」 そう思っているだけでは進まないので、いろいろ調べてやっとわかったことを挙げていきます。

    素直にREADME

    製品を買ったら必ず説明書から読む人は存在しないと思いますが、説明書はマジで大切です。 インストールしたnode_modulesから、使用しているパッケージを探し、README.mdを見れば解決することも。

    ある程度のアレンジを、製作者が事前に用意してくれています。 VSCodeの人は右クリックし「プレビューを開く」とすれば見やすいです。

    シャドーイングでアレンジする

    node_modulesから使用しているパッケージを探し、 自分のプロジェクトにコピーして編集することにより自分好みのページに変更することができます。

    例えば、gatsby-theme-minimal-blogの記事のスタイルを変更したい場合、

    node_modules
    └── @lekoarts
        └── gatsby-theme-minimal-blog
            └── src
                └── components
                    └── layout.tsx

    をコピーし、自分のプロジェクトで

    src
    └── @lekoarts
        └── gatsby-theme-minimal-blog
            └── components

    という構造のフォルダを作り、ファイルを貼り付けます。

    ファイル内でimportされているファイルも再帰的にコピーしておく必要があります。

    そして、記事内の変更したいタグにスタイルをつけていきます。

    const Layout = ({ children, className = `` }: LayoutProps) => (
      <MDXProvider components={MdxComponents}>
        <Global
          styles={(t) => ({
            "*": {
              boxSizing: `inherit`,
            },
            "[hidden]": {
              display: `none`,
            },
            "::selection": {
              backgroundColor: get(t, `colors.text`),
              color: get(t, `colors.background`),
            },
            // ここにタグのスタイルを追加していく
            "hr": {
              marginTop: `2rem`,
              marginBottom: `2rem`,
            },
          })}
        />

    クエリデータから変更する

    componentsのファイルはクエリされたデータに対してどう表示するのかといった機能をつかさどると考えれば理解が早いです。

    ではクエリデータから変更したい場合はどうすればいいのでしょうか?

    useStaticQueryを使ってコンポーネントからクエリする

    例えば、トップページや記事一覧にサムネイルが無いスターターの場合、 クエリから変更することで記事のFrontmatterからデータを引っ張って来れます。 今回扱ったgatsby-theme-minimal-blogでは「banner」という画像のフロントマターが coreのgatsby-node.jsで定義されていたのでクエリできました。

    事前に画像データを扱うためのプラグインをインストールしておきます。

    yarn add gatsby-plugin-image gatsby-plugin-sharp gatsby-transformer-sharp
      plugins: [
        `gatsby-plugin-image`,
        `gatsby-plugin-sharp`,
        `gatsby-transformer-sharp`,

    gatsby-theme-minimal-blogの場合はhomepage.tsxが記事の一覧のクエリデータを受け取り、 listing.tsx→blog-list-item.tsxとデータを渡していました。 大元でデータをクエリし、それぞれのコンポーネントで画像データとして受け取るように変更します。

    ......
    import { graphql, useStaticQuery } from "gatsby"
    import { IGatsbyImageData } from "gatsby-plugin-image"
    
    export type MBBlogProps = {
      posts: {
        slug: string
        title: string
        date: string
        excerpt: string
        description: string
        timeToRead?: number
        tags?: {
          name: string
          slug: string
        }[]
        // サムネイル用の項目を追加
        banner?: {
          childImageSharp?: {
            gatsbyImageData: IGatsbyImageData
          }
        }
      }[]
    }
    const Homepage = () => {
      const { tagsPath, basePath } = useMinimalBlogConfig()
      // useStaticQueryで記事のフロントマターからサムネイルデータ(banner)をクエリしたpostsを作成する
      const data = useStaticQuery<{
        allPost: {
          nodes: MBBlogProps[]
        }
      }>(graphql`
        query HomepageQuery {
          allPost(sort: { date: DESC }) {
            nodes {
              slug
              title
              date(formatString: "YYYY-MM-DD")
              excerpt
              description
              timeToRead
              tags {
                name
                slug
              }
              banner {
                childImageSharp {
                  gatsbyImageData(width: 800, placeholder: BLURRED)
                }
              }
            }
          }
        }
      `)
      const posts = data.allPost.nodes
      return (
        <Layout>
          <Listing posts={posts} sx={{ mt: [4, 5] }} />
          <Flex sx={{ alignItems: `center`, justifyContent: `space-between`, flexFlow: `wrap` }}>
            <Link
              sx={(t) => ({ ...t.styles?.a, variant: `links.secondary`, marginY: 2 })}
              to={replaceSlashes(`/${basePath}/${tagsPath}`)}
            >
              View all tags
            </Link>
          </Flex>
        </Layout>
      )
    

    そしてデータを受け取るコンポーネントでもサムネイル項目を増やし、

    ......
    import { IGatsbyImageData } from "gatsby-plugin-image"
    
    type ListingProps = {
      posts: {
        slug: string
        title: string
        date: string
        excerpt: string
        description: string
        timeToRead?: number
        tags?: {
          name: string
          slug: string
        }[]
        // サムネイル用の項目
        banner?: {
          childImageSharp?: {
            gatsbyImageData: IGatsbyImageData
          }
        }
      }[]
      className?: string
      showTags?: boolean
    }
    

    最終的な記事一覧の1要素を表示するコンポーネントでサムネイルを表示するようにします。

    ......
    import { GatsbyImage, getImage, IGatsbyImageData } from "gatsby-plugin-image"
    
    type BlogListItemProps = {
      post: {
        slug: string
        title: string
        date: string
        excerpt: string
        description: string
        timeToRead?: number
        tags?: {
          name: string
          slug: string
        }[]
        // ここでもサムネイル用の項目を追加
        banner?: {
          childImageSharp?: {
            gatsbyImageData: IGatsbyImageData
          }
        }
      }
      showTags?: boolean
    }
    
    const BlogListItem = ({ post, showTags = true }: BlogListItemProps) => {
    
      // 記事のフロントマターにbannerが指定されていればimageを作成し
      // Link内にサムネイルとして表示する
      const image = getImage(post.banner?.childImageSharp?.gatsbyImageData)
      
      return (
      <Box 
      sx={{
        borderRadius: `2xl`,
        boxShadow: `lg`,
        overflow: `hidden`,
        bg: `background`,
        p: 3,
        transition: `all 0.3s`,
        '&:hover': { boxShadow: `xl`, transform: `scale(1.01)` },
      }}>
        <Link to={post.slug} sx={(t) => ({ ...t.styles?.a, fontSize: [1, 2, 3], color: `text` })}>
          {image && (
            <GatsbyImage
              image={image}
              alt={post.title}
              sx={{ borderRadius: `lg`, mb: 3,
                height: `10rem`, // 高さを固定
                width: `100%`,  // 幅を100%にして親要素に合わせる
                objectFit: `cover`, // 画像がはみ出さないようにリサイズ
               }}
            />
          )}
          {post.title}
        </Link>
    

    終わりに

    シャドーイングする際、どこで何を扱っているのかを探し出すのが一番のネックです。

    これを解決するには自分の経験と語彙力、それと「ぶつかり稽古」しかありません。

    ※追記:結局GatsbyJSは扱いづらく、ビルドも遅いのでastroに移行中・・・




    Copyright 2026
    サイトマップ