ブログをFreshからNext.jsに移行しました

作成日
更新日

どうも。Reoです。

最近このブログFreshに移行したばかりですが、訳あって次はNext.jsに移行しました。今回は移行理由と過程について紹介していきます。

あらすじ

Next.jsに辿り着くまで話が長いので簡潔に。

  • Fresh+サブモジュールを脱するためにSupabaseを使って構築した。
  • 出来上がったサイトはSSRでbotにより毎分アクセスされSupabaseのリクエストが大変なことになった。
  • FreshSSG対応ができず、泣く泣くNext.jsに移行。
  • SSGに対応したが、しかし...

という感じです。

背景

2024年10月にこのブログWordPressからFreshに移行しました。半年前ですね。

公開した関連記事は次のとおりです。

Denoというランタイム環境が好きで(というか見目が好きで)、そのDenoを使ったFreshを選択して、長年使ってきたWordPressとお別れしました。

その時の記事取得はGitHubを使い、サブモジュールから取得するという方法をとりました。

抱えていた問題点

Freshに移行した後、次の問題を抱えていました。これはFreshを選んだからというより、自分の設計がよろしくなかったのが原因だと思います。

  • フォルダ構成が微妙で、階層が深く、書く時に開くのが面倒
  • 画像が重い(全てをサブモジュールにおいていたのと遅延読みこみしていなかったからかな)
  • サブモジュールの扱いが結構大変だった
    • 開発時に git submodule update --remote してからブランチを切れよとかいうルールをつけていたけれど、それも面倒

あんまり書いてないけれどプライベートのメモはコレです。

エディタとして、Obsidianを利用しているんですが、とにかく階層が深くて、新規に書くのも修正をしにいくのも面倒でした。

新しいシステムに変えたぞ!ということ以外、WordPress時代と別に書きやすくなったわけではありませんでした。マークダウンで書けるってことぐらいでしたね。

Obsidianの神との出会い

Minervaというサイトに出会いました。本当にかなり衝撃を受けました。 これについては、「俺的Obsidianのつかいかた」という記事にも書いていますので詳しく気になる方はこちらも読んでみてください。

Minervaと出会い、Obsidianの使い方を変え、さらにObsidian Publishに寄せたブログにしたい!という思いが芽生えました。(ここでObsidian Publishを使わないのが自分らしい)

Fresh+Supabaseへの移行

まずは Fresh+Supabaseへ移行をしました。Supabaseは検索性が高くなるという理由で導入しました。実はSupabaseを利用するのは初めてです!

その時のメモはこちらです。 FreshでObsidian Publishライクなブログを目指す

主にやったことは次のとおりです。

  • サブモジュールからのコンテンツの取得をやめてSupabaseから取得するようにした
  • Obsidian保管庫を1つにして、個人のメモとブログをまとめた。
    • メモは公開前提では書いてないけれど、内容的に公開できるものはなるべく公開する方針

これにより、ブログにもメモを貼り付けられるようになりました。

公開前提のブログとして記事を書くのは、書くぞ!と意気込んでから書くので、どうしても記事数は多くは書けません。ですが、そういう記事も書きたい。でもそうじゃないメモにも人に役立つものはたくさんあるはず...という意味で今回の運用方法に移行しました。

ちなみに、記事がこの仕組みに変えて初めての記事ですが、書いていていい感じです!変えてよかった!

移行後の問題点

2週間ぐらいかけて移行しました。Freshで全ページ共通のサイドバーを作ったり、Freshで記事読み込み中にローディングを表示したり、この辺りがめちゃめちゃ苦戦しました。

FreshのプロジェクトをDenoDeployでデプロイするところまで頑張って、よし終わったぞー!と思ってSupabaseを見ていると、異様なほどリクエスト数が来ているわけです。

Supabaseのリクエストログを調査して、色々対策をしてみて気付きました。クローラーがアクセスするたびにSupabaseへリクエストをしている...!しかし記事は検索エンジンにインデックスされて欲しいので、防ぐわけにもいかない...!

また、Deno Deployの仕組みもあり、botのリージョンに合わせてFreshが起動するので、それに合わせてさらにリクエストが...

そんなこんなで、SSGに移行せねば!となりました。

Next.js+SSGに移行

本当はFreshのままSSGに移行するつもりでしたが、これは非常に難しいです。詳しくは次のメモを見てください。

ここで、ようやくFreshの利用を諦めました。

Supabaseを使わないのであれば、Freshのままでもよかったかなと思いましたが、結局Deno Deployの容量もあるし...変えてよかったんじゃないかなと思います。

ありがとう、Fresh。私の脱WordPressの重い腰をあげてくれてありがとう。短い間だったけど楽しかったよ...

FreshからNext.js

数年ぶりにNext.jsを触りましたが、すごいですね。Freshで苦戦したあらゆる痒いところに届いてくれる感じがしました。

変換スクリプトをDenoで動かして、ちょいちょいっとNext.jsに変換していき、30時間ぐらいでSSGに対応したブログへ移行ができました。

さらなる問題点

さて、SSGに対応したら全て解決できると思っていましたが、予想が外れました。

  • SSRではアクセスされた時にSupabaseへのリクエストがされる
    • bot が毎分リクエストしているので、実質毎分1回はリクエストされていた
  • SSGの場合、ビルド時にSupabaseへのリクエストがされる
    • Obsidianでメモを更新して git push するたびに再ビルドする
    • ビルドごとに全てのページを再生成するので、毎ビルドごとに記事数分のリクエストがされていた。
      • 今だけでも 300〜400件ぐらい記事があるのです。
      • しかも自分は保存が癖になっているせいで...

恐ろしいことに、SSGに置き換えたことによって、リクエスト数が増えました。こんなはずでは...

オンデマンドISR対応

差分だけを更新する機能はないのか調査したところ、ありました!すごい!

On-demand ISR(Incremental Static Regeneration)という機能がNext.jsにあり、これを使うと再ビルドすることなく差分のみをSSRのように更新することができます。

詳しくは調査時のメモを見てください。

これにより、無事にSupabaseへのリクエストされすぎ問題が解決しました!

Next.jsの進化に頭が上がりません。

まとめ

ということで、Next.js+Supabase+オンデマンドISRの形に移行しました。

Next.js時代 (これから) Fresh時代 WordPress時代
フロントエンド Next.js Fresh 🍋 (フルスタック) WordPress
コンテンツ管理 Supabase GitHub サブモジュール (DBは使っていない) WordPress(MySQL)
サーバー Vercel (サーバーレス) [Notes/Deno Deploy|Deno Deploy] Xserver
コンテンツエディタ Obsidian Obsidian WordPress の Classic Editor
ローカル環境 Node.js 環境 Deno 環境 VVV
デプロイ方法 Vercel Deno Deploy wordmove

今回のアップデートで、Freshに移行した時にはじめた日報はやめて、WeeklyReportも書き始めました。よりリアルタイムを感じたい人は読んでみてください。

おわりに

この記事がこの運用方法に変えてからの初めてのブログ記事です。リンクが多くて見づらいかな、どうでしょうか。

私側(書き手側)からすると、明らかにFresh時代からも、WordPress時代からも絶対に楽になっている自信があります。

Next.js への移行(ISR対応を含む)は約2日間(40時間)フルコミットで完了しました。うまくいって本当によかったです。

まだまだトップページの実装もしていない不完全な状態ですが、記事やメモやWeeklyReportを更新しながら気長に直していこうと思っています。また、移行に伴い過去記事の画像が参照切れを起こしていたりするので、それもチマチマ直していきます。

公開前提ではなかったメモもなるべく公開するようにしていくので、これまでのブログとは少しちがった形になっていくとは思いますが、これからも うるおいらんどをよろしくお願いします!

サイトアイコン
公開日
更新日