フリーランスの暇な時に書く技術メモ
Genki Tech

ウェブサイトを Gatsby V3 と Material UI V5にアップグレード

Gatsby と Material UI のメジャーバージョンがいつの間にか上がっていたので、本サイト Genki Tech に適用しました。個人的に勉強できたことなどをまとめただけの、ほぼ自己満足の記事です。

本サイトは Gatsby と言う React 製のいわゆる JAMstaci サイトですが、Web 初心者の頃に速攻で立ち上げたものなので、単純にライブラリのアップデートだと全然動きませんでした。

Gatsby プロジェクト自体も適当なテンプレを使っていてよく分からないコードが残っていたり、なんちゃって TypeScript になっていて、折角の GraphQL が型生成せずに Any で使いまわしていたり、theme-UI と styled-component と material UI がゴチャゴチャしていてわけわからん状態になってしました。

なのでバージョンアップは諦めて 1 から作り直し、旧バージョンから移植して動くようにした感じです。

Getsby V3 って何が違うの?

画像ファイルが少し使いやすくなったくらいで、実はそんなに変わりません。でも少しずつ上げといたほうが付いていけなくならないのでいいと思います。

V2 ではプロジェクト内の特定の画像を表示するために Static な GraphQL から取ってくるのでファイル名で簡単に指定できないなどの問題がありましたが(対処方法はいろいろありますが)、V3 からはその辺をすっきりまとめた gatsby-plugin-image というパッケージがあり、StaticImage タグで呼び出せるようになりました。

あとは処理速度が少し上がったらしい。

StaticImage

以下のように書くだけで、特定のファイルを表示できます。blurred を指定するとモヤっとロードされます

<StaticImage src="test.png" placeholder="blurred" alt="test" />

GatsbyImage

allmarkdownRemark などでクエリを取ってくるときに以下の様に取得できます。layout: FULL_WIDTH が今までの Fluid ですね。

...
image {
  publicURL
  childImageSharp {
    gatsbyImageData(layout: FULL_WIDTH, placeholder: BLURRED)
  }
}
...

表示するところはこれだけです。

<GatsbyImage
  image={node.frontmatter.image.childImageSharp.gatsbyImageData}
  alt={node.frontmatter?.title ?? ''}
/>

Material UI V5 って美味しいの?

ハイ。美味しいです。V5 から MUI にブランド名が変わったらしく、大幅に機能が増えていますが、今までの機能も基本的には使えます。

特にデザインシステムが変わっていて、theme-UI などで使えた sx プロパティが使用できるようになります。例えば以下のように書くと、style={{}}の指定と異なり、ちゃんと className 的にスタイルが適用されます。

sx props

<Button sx={{ mx: 2 }} />ボタン</Button>

sx が使えて div に仕える Box と言うコンポーネントも用意されています。テーマカラーも以下の様に使用できます。

<Box sx={{ color: 'primary.main' }} />

styled

Material UI 以外のコンポーネントでスタイリングしたい場合、styled 機能を使用し、スタイルを定義したコンポーネントを手軽に定義できます。

例えば以下のように Gatsby の Link コンポーネントを、MUI のテーマの値を使用してスタイリングしたり出来ます。

const StyledLink = styled(Link)(({ theme }) => ({
  fontSize: '20px',
  paddingLeft: theme.spacing(4),
  paddingRight: theme.spacing(4),
  paddingTop: theme.spacing(2),
  paddingBottom: theme.spacing(2),
}));
...
<StyledLink to='...'>link</StyledLink>

レスポンシブ対応

これが凄くよく出来ていて、以下のように書くとその幅毎に値を切り替えることが出来ます。

xs や sm などを何ピクセルにするかはカスタマイズできます。

marginBottom: {
  xs: 0,
  sm: 1,
  md: 2,
  lg: 3,
}

GraphQL の型の自動生成

GraphQL って便利だけど、GraphQL 書いて、TypeScript で取得するための型情報も書いて、めんどくさいなと思いませんか?思ってました。でも書く必要なかったみたいです。

gatsby-plugin-graphql-codegen と言うプラグインを使用すると、以下のように書けました。

export const IndexTemplate: React.FC<{
  className?: string;
}> = () => (
  <StaticQuery
    query={graphql`
      query IndexTemplate {
        allMarkdownRemark {
          edges {
            node {
              frontmatter {
              	省略...
              }
            }
          }
        }
      }
    `}
    render={(data: IndexTemplateQuery) => { ←ここの型が自動生成される!
      let edges = data.allMarkdownRemark.edges;
      省略...

上の IndexTemplateQuery が自動生成されます。今までここにクエリが返す型情報を自前で書いて、書き間違えたりして値が入ってないなんてこともありましたが、これで大分扱いやすくなりました。

余談

スタイリングを Material UI に統一できたのでライブラリの依存関係がすっきりしました。最初にもっときれいに書いていれば単純に移行できたかもしれません。おかげで丸一日かかってしまいました。

スタイリングを直書きすることは今でも賛否両論あるんでしょうか。今はコンポーネントが使いまわせるので直書きしてテーマで一括で変えれるようにするのがベストだと思っています。