👻

GitHubだけでヘッドレスCMSを再現しよう!

2023/02/18に公開

これはヘッドレスCMSとは呼ばないのでは…

はじめに

こんにちは。とある大学の1年生をやっております。

2,3ヶ月前から、所属サークルのホームページを一から作り直すプロジェクトを始めており、なんと、プロジェクトメンバーは僕1人(泣)

今回は、ヘッドレスCMSを使いたいけど使えない事情と、その解決策(?)について書きました。

前提

  • Next.js13でSSGして使う。
  • GitHub Actionsでデプロイする。

ヘッドレスCMSとは

最近のフロントエンドでは非常に良く使われています。すでに様々なサービスが存在しており、

  • コンテンツの保存・管理
  • コンテンツ取得用のAPIの提供(Rest, GraphQL)
  • エディタ(マークダウン, リッチテキスト)
  • GitHub Actionsのトリガー(デプロイ)
  • チーム管理(権限など)

などが機能としてあります。

ヘッドレスCMSがどのようなものか、詳しくは以下のサイトなどをご覧ください。

https://blog.microcms.io/what-is-headlesscms/

ヘッドレスCMS導入への壁

僕が求める要件はこんな感じ

  • 本体リポジトリにコミットせずに、記事を更新したい
  • 記事を更新する人の手間を増やさない(新規アカウント登録など)
  • サーバーなしで運用したい
  • できれば新しいサービスを利用せずに済ませたい
  • 無料

部所有のサーバーがない、旧サイトを誰も更新しなかった、僕が下っ端なので部のアカウントを管理できない、などが理由です。

Strapiが最有力候補のヘッドレスCMSでしたが、やはり要件を満たしきれません…

おっ!

ここで注目。Githubは、ブラウザからプレビュー付き簡易エディタを使えます。

まず、マークダウン置き場のリポジトリを新規作成します。こちらでは、メインブランチのみ使用し、を 「保存 = メインに直コミット」 とします。

これにより、

  • 部員なら誰でも
  • ローカル・ブラウザ・モバイルアプリのどの環境からでも編集できて、
  • git関連の面倒な手順なく
  • 本体のシステムを更新せずに、

CMSとして使える!!

画像もアップロードできるので、画像だけはpublic/ディレクトリに置かなければならないと言う不便な点も解消されます!!

どうやってデータ取得するのさ

普通、ヘッドレスCMSでブログといえば、RestやGraphQLなどのAPIをビルド時にたたき、データを取得します。

GitHubのリポジトリからデータ取得するAPIなんてあるのか?と思うかもしれませんが、簡単です。

「ビルド時にリポジトリをクローン」

すればいいんです!

実装について

まず、リポジトリをcontentディレクトリにクローンする下記ファイルを作成します。

src/prebulid.sh
git clone --depth 1 https://github.com/organization-name/CMS用gitリポジトリ.git content

次に、package.jsonを編集します。

package.json
...
  "scripts": {
+   "prebuild": "bash ./src/prebuild.sh",
    "build": "next build",
...

npm-scriptsの機能で、npm run buildbuildの実行をすると、先にprebuildが実行されます。これで、ビルド直前にデータを取得できますね。

マークダウン変換処理

メタデータの抽出にgray-matter、変換処理にunifiedとそのプラグインを使います。

  • ビルド時に、マークダウンからタイトルや日付等のメタデータを抽出した後、HTMLに変換
  • クライアント側で表示する際、HTMLからReact Componentに変換

長くなるので、ここでは詳しく解説しません。

こちらの記事が非常に参考になりました。

https://www.haxibami.net/blog/posts/blog-renewal

また、Vercelが様々なテンプレートを用意しているので、それらのソースコードを見てみるのも参考になると思います。

その他小細工

ブラウザエディタからコピペで画像をアップロードする際は、自動的にURLを割り当ててくれるので問題ないのですが、画像ファイルを単体でアップロードし、相対パスで表示したい時もあります。

例えば、webp画像はブラウザエディタでサポートされていませんし、ローカルからはそもそも自動でURLを割り当てられません。

そこで、裏技的に、GitHubのraw表示を使います。

実は、https://raw.githubusercontent.com/organization-name/リポジトリ名/ブランチ名/該当ファイルのパスとすることで、画像を取得できます。

utils/ディレクトリなどにパース用関数を用意し、先ほどのHTMLからReact Componentに変換する際や、メタデータに含まれるサムネ画像URLなどを取得する際に、パース処理を挟めば完璧です!

まとめ手順

  1. CMS用リポジトリにてマークダウンファイルを追加・編集
  2. mainにコミットすることで保存
  3. 本体リポジトリにて、手動でデプロイ用のGitHub Actions workflowを実行
  4. ホームページが更新

おわりに

2つの別リポジトリが密結合な状態にあるのがちょっと気になりますが、今後新しくホームページを作り直すことになっても使いまわせそうなので、やっぱりこれで正解だったと思います。

今後は、もっとワンポチくらいでデプロイできる仕組みを考えたいですね。コミュニケーションツールとして使ってるDiscordにそれ用のbotを入れるとか…?

P.S) 本当はソースコードのリンクを貼ろうと思ったのですが、あくまでサークルの所有物なので、ここに貼るのは控えました。Publicなリポジトリなので、上手く探せば見つけられると思います。

Discussion