gates1deのブログ (仮)
このブログを支える技術 -後編-

Tech作成日: 2021-03-08 (最終編集日: 2023-04-02 )

👍🏻今回の改善ポイント ・コードの syntax ハイライトが表示されるようになりました! ・Youtube動画の埋め込みに対応しました!

おさらい

前回のブログ では, このブログで使っている Web Framework やデプロイツール等について紹介しました. 今回は記事を書いてデプロイするまでの流れや, 一部コードの紹介をしていこうと思います. Next.js の ISR ってどんなもんや? と思っている方も簡単に動きを紹介するので, それだけでも見ていただければと思います 🙇🏻

記事がデプロイされるまでの流れ

Notion をバックエンドにしているので, 記事自体は Notion 上で書いています. とあるページ (ホームと呼びます) の下に, カテゴリ分け (Daily や Tech など) されたページが存在しておりまして, これらのページは Notion テンプレートの「List」になっています. List のページを作ると, そのページの下にページを作成していくことができるので, これを1つ1つの記事ページとして作成しています. ただし, 記事は一気に書き上げるわけではないので, 中途半端な状態でページを作って保存すると恥ずかしいことになります 😅 なので記事を書くときは「Drafts」という List のページを作ってそこに書き溜めています. そして完成したら各カテゴリのページに移せば記事が掲載されます. 今はこのブログは完全に静的サイト (クライアント側でデータ取得等をしていないサイト) なので, ビルド&デプロイしないといけないところですが, ここで便利なのが Next.js の SSR と ISR です. SSR については, トップページのところで記事一覧が表示されているのですが, ここで利用しています. ISR よりも情報の鮮度が重要なので, アクセスされるごとに最新の記事リストを取得するためです. 詳細は省略しますが, ページコンポーネント (NextPage) 内で getServerSideProps を実装して export すれば実現可能です. ISR については, 各記事ページで利用しています. ページコンポーネント内で, getStaticPropsgetStaticPaths という関数を使うと ISR が実現可能なのですが, 下記に例を示してみましょう (実際のコードとは関係ありません).
import { GetStaticPropsResult, NextPage } from 'next'

import { NotionAPI } from 'api/notion-api'

// ...

type Props = {
  data?: any
}

type StaticProps = {
  params: { pid: string }
}

const Post: NextPage<Props> = ({ data }) => {
  return (
    <PostContent data={data}>
  )
}

export const getStaticProps = async ({ params }: StaticProps): Promise<
  GetStaticPropsResult<Props>
> => {
  const notionAPI = new NotionAPI()
  const data = await notionAPI.fetchData(params)
  return {
    props: { data: data },
    revalidate: 1,
  } as GetStaticPropsResult<Props>
}

export const getStaticPaths = async () => {
  const notionAPI = new NotionAPI()
  const paths = await notionAPI.fetchPaths()
  return {
    paths: paths,
    fallback: false,
  }
}

export default Post
細かい説明は抜きにして, ポイントとなるのは ・getStaticPropsgetStaticPaths を export すること ・GetStaticPropsResult にある revalidate に 数値を設定すること ・getStaticPathsfallback を設定すること によって ISR がおこなわれます. revalidate は, ある時点でのアクセスから何秒間以内は検証 (サイトの再生成) をしない, という設定で, これを1秒などにすればほぼすぐにサイトが更新され, 常に最新の状態を保つことが可能です. fallback は, paths に該当するパスのページが存在しない場合に 404 を返すかどうかのフラグです. false にした場合はクライアント側で 404 ページを描画する必要があります. 詳しくは公式を参照するか, こちらの方のzenを参照してください. 結果, fetchData で取得したデータに更新があり, ISR の条件が満たされると裏側 ( Vercel 内部で動いている Next.js アプリ) で自動的にページを再生成してくれます. 百聞は一見に如かずということで, ちょっと動きを見てみましょう.
revalidate の値を60にしておきます ① 記事ページへアクセス ② notion で記事を編集 ③ 60秒以内に何回か記事ページを更新 → 内容が変更されていないことを確認 ④ 60秒経過後に再度記事ページにアクセス → 内容は変更されていないが, 裏でページが再生成される ⑤ もう一度記事ページを更新 → 内容が変更されている 大体流れはつかめたかと思いますが, ④・⑤ で「え? 2回アクセスしないと更新されないんか?」と思われた方もいるでしょう. 大丈夫, 誰かがそのページに revalidate 秒後にアクセスしておけば他の人は④ですぐに更新されるので, 自分がアクセスしてしまえば問題ないです 🙂🙂🙂 ブログに限らず, 静的なページについてはその仕様で十分だと個人的には思います. 以上が記事を書く〜デプロイまでの流れになります.

現状困っていること

特にはないんですが, 例えば mdx で作るブログよりは各ページのカスタマイズ性は低いです. ですので, そのページだけに特定のコンポーネントを置きたい場合, 共通ページ ( [slug].tsx など ) に組み込んで上手いこと表示のハンドリングをする必要があります. 今回のブログに関しては, そういう要件は排除するようデザインしていけば困らないかなとは思います. また, カテゴライズはできるとして「検索機能」はまだイメージが掴めていません. そもそも Notion API でそれが可能なのかを調べることから始まりますが, なかったときは自前でデータを用意して API を作るしかないかなと思っています. まぁ, 一個人のブログなのでコンテンツはそんなに増えないでしょうし, パフォーマンスは考えなくて済みそうな気もするので, もし実装するとなったらまずは小手先の実装をしてみようかなと思います 👨🏻‍💻

おわりに

大体このブログについては一通り紹介したので, 次回以降はプログラミングに関係ない記事やミニマムな内容の記事を書いていこうかなと考えています. あとはとにかく色気のないブログなので, サイト自体の作り込みをしないといけないので, そっちメインになるかなとは思います笑 それでは, 最後まで見てくださってありがとうございました!さよなら〜