2023-02-19

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

by @ojii3

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

はじめに

こんにちは。農工大で1年生をやっております。

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

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

前提

ヘッドレスCMSとは

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

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

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

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

ヘッドレスCMS導入への壁

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

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

最有力候補だったStrapiというヘッドレスCMSでさえ多くの要件を満たせません。

おっ!

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

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

これにより、

CMSとして使える!!

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

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

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

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

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

すればいいんです!

実装について

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

src/prebulid.sh
rm -rf content
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とそのプラグインを使います。

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

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

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を作って入れるとか…?

最後に、ソースコードを貼っておきます。

https://github.com/tuatmcc/homepage2.0

https://github.com/tuatmcc/hp-md-content

← 記事一覧に戻る