自分のブログが負債化していたのでリファクタリングした。

2020-09-25

自分のブログにも関わらず色々と負債があったので、リファクタリングと少し機能を追加してみた。数も少ないので2日掛からない程度で完了したのでやったことをまとめる

今までのブログ

このブログを作ったのは、2019年の12月なので約10ヶ月経過しており開設時からブログはちょこちょこ書いているものブログ自体はGatsbyでテンプレートとしてgatsby-starter-blogを使用していてほぼそのままの状態だった。

ざっくりまとめると以下のような感じ

  • tsxファイルがclassベースで書かれている
  • コンポーネント化されていない(ヘッダーとフッターぐらいしかない)
  • anyばっかり
  • cssがグローバルなSCSSのみで管理している
  • ブログに必ずと言っていいタグ機能がない
  • シンタックスハイライトが白黒

上記を何とかしようと思ったので今回リファクタリングを行った。

class構文を辞めてReact.FCにする。

全ファイル対応した。anyも撲滅した。Gatsby.js を完全TypeScript化するの記事を参照に対応してみたが、1点だけgatsby-plugin-graphql-codegenを使ってのGraphQLの型定義だけは、今回は対応していない。理由はこのプラグインを導入して開発していると、ローカル環境が重くなってしまい作業に支障が出てしまった(何故かは調べていないのでこれから調べる予定)のと、全スキーマは使わんやろと判断したため今回は、必要そうな型定義ファイルを自前で用意した。

export type Frontmatter = {
  title: string
  date: string
  tags?: string[]
}


export type MarkdownRemark<FrontmatterKeys extends keyof Frontmatter> = {
  id: string
  excerpt: string
  html: string
  tableOfContents: string
  frontmatter: Pick<Frontmatter, FrontmatterKeys>
  fields: {
    slug: string
    filePath: string
  }
}

こんな感じで用意してコンポーネント側でimportして使用した。

// 一部抜粋

import { MarkdownRemark } from "../types/blog-post"

type Props = {
  data: {
    markdownRemark: MarkdownRemark<"title" | "tags">
  }
  pageContext: {
    slug: string
  }
}

const BlogPostTemplate: React.FC<Props> = ({ data, pageContext }) => {
  const post = data.markdownRemark
  const { slug } = pageContext

  return (
    <Layout
    title={post.frontmatter.title}
    slug={slug}>
      <SEO
        title={post.frontmatter.title}
        description={post.excerpt}
      />
      <Post post={post}/>
    </Layout>
  )

}

クエリは以下のような感じで書きます。

query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      excerpt(pruneLength: 160)
      html
      frontmatter {
        title
        date(formatString: "YYYY-MM-DD")
        tags
      }
    }
  }

GraphQLでpublishedupdatedが取れるので記事の更新日とかも取れるのだが今回は対応していない。

styled-componentsの導入

Tailwindcssに置き換えしてしまうか悩んだが、まだ小慣れていないこともありstyled-componentsにした。全部グローバルなSCSSで管理していたがコンポーネントの中にCSSを閉じ込めるだけ閉じ込めた。ただ完全移行はできておらず、そもそもデザインも大規模にリニューアルしたいなと思っているので少し負債が残った。

コンポーネント化

そこまで大規模なサイトでもないので別にいいかとも思ったが、Reactの思想に反してそうだったのでヘッダー・フッター以外にも記事のリスト部分や、タグの表示、SNSのシェア、ダークモードに切り替えるボタンなどをコンポーネントとして切り出した。

ダークモード切り替えボタン

今まではお使いのPCのシステムに応じて自動的に切り替えをしていたが、右上のボタンから自由に切り替えができるように追加実装した。単純にデバッグする時にシステム設定で切り替えするのが面倒なのが最大の理由だ。今回は、gatsby-plugin-dark-modeというプラグインで実装した。実際のプルリクを見ると分かりやすい。

ThemeTogglerというgatsby-plugin-dark-mode内のコンポーネントを呼び出しチェックボックスの状態でbodyにdarkというclassが付与されるので、後はCSSをいい感じにすればサクッと実装できる。次の訪問時に同じ設定にしておくためLocalStorageにフラグを保存している。正直この程度であればロジックはそこまで難しくなさそうだが導入するだけなのですぐ終わった。

シンタックスハイライト

今まではCSSで白黒で表示していたものをgatsby-starter-blogに標準で入っているprismjsを使った。VSCodeのようなテーマを選んだ

タグ機能の実装

参考になる記事は色々あって適当に拾ってやってみて実装できたのだが、lodashを使っていたりしてちょっと簿妙かなと思ったので、違うやり方を検討した。

調べてみて参考にさせていただいたのが、うひょさんのuhyo/blogで、技術構成がほぼ同じなので大変参考になった。またsadnessOjisanさんのGatsby製のブログにタグ機能を追加するための方法を見直してみようの記事も勉強になった。

これからやること

結構頑張った(最初からやれよという感じだが。。)ので今回はこのくらいにした。目次機能も実装はしたのだがスマホ時のレイアウトが決まらず今回は見送った。

デザインの見直し

dev.toのようなデザインにしたいなーと思うのでデザインを1から見直しするかも

OGP画像

今はないので適当にアイコンでも表示しようかなとも思ったがやっぱり記事ごとに違うOGP画像を用意したい。

記事の更新日も表示するようにする

これはすぐにできるのでそのうちやる。今は以下のようなクエリになっている。

{
  allMarkdownRemark(
    sort: { fields: [frontmatter___date], order: DESC }
    limit: 1000
    filter: { fields: { sourceFileType: { eq: "blog" } } }
  ) {
    edges {
      node {
        fields {
          slug
        }
        frontmatter {
          title
        }
      }
    }
  }
}

このfrontmatter___datefrontmatter___publishedにしてpublishedupdatedの型定義とクエリを追加すればOK

Aboutページの作成

自分のブログにREADME的なページを用意しておけば自己紹介にもなるので作る。

全文検索

実装してみたい。やっぱりAlgoliaとか使う感じなのかまずは調べる作業から。。。

キャッシュ周り

全然対応していないので、Netlify側の環境変数などもろもろ対応したい。


ソースコードはこちらのリポジトリにあります。

Google Analyticsを使っています。