🗃️

microCMS × Gatsby × GitHub Actions × S3 で自社記事をCMS化した話

2024/03/28に公開

こんにちは。株式会社IVRy(アイブリー)のエンジニアのsagawaです。

IVRyでは現在、自社記事を部分的にContents Management System(以降CMS)にて管理・編集しています。今回はこのCMS導入の背景、それに伴う課題と対策、またその構成について紹介したいと思います。

CMS導入の背景

これまでの自社記事の運用

IVRyでは導入事例お役立ち記事といった自社記事が多数存在します。この取り組みはマーケティング施策の大きな柱となっており、IVRyのユニークなポイントの一つです。

https://note.com/teru_ivry/n/na8b676ae957d

これらの記事は従来、プロダクトとしてのIVRyの一部として生成されてきました。IVRyの技術構成は以下の記事の通りですが、フロントエンドはNext.jsを用いてStatic Site Generation(以降 SSG)にて静的サイトを生成、S3とCloudFrontを用いて配信しており、記事ページもこの中に含まれる形となっていました。

https://zenn.dev/ivry/articles/6c85815e52ad7a

自社記事のデータはこれまでマークダウン形式で管理されており、記事入稿者がそれらのファイルを作成後に所定のストレージへ格納、そのファイルを先述のSSGにてビルドをする際に読み込んで記事ページを生成するという運用でリリースされてきました。当時の記事管理の状況は以下の記事にも書かれているので、気になる方はご参照ください。

https://zenn.dev/ivry/articles/e4a13bd03b91ae

記事運用の課題

記事の種類や数が少ないときはこれで十分対応できていたのですが、IVRyの規模が拡大し記事数も増え内容も多様化してくると、様々な課題が顕在化してきました。開発観点と運用観点のそれぞれで見ていきます。

開発観点

自社記事をIVRyプロダクトの一部としてリリースしていたことは先述の通りですが、記事の数が多くなるにつれ、リリースにかかる時間のうちの大半を記事生成の時間が占めるようになってきました。サーバスペックを上げることである程度の時間を短縮することは可能なものの根本解決にはならず、リリースにかかる負荷は日々増加する状況でした。

また記事の数が増え内容も多様化してくると、記事に親子関係を持たせたりカテゴリーを付与して関連させて表示させるといった新たな機能が必要になってきます。これに伴い記事データのマークダウン形式の独自化が進み、解析処理も複雑化します。コードベースの見通しもだんだんと悪くなり、記事に関する処理の学習コストが増加、また保守性が低下しつつある状態でした。

運用観点

記事の公開はプロダクトのリリースサイクルよりも速度感をもって実施したい場合があります。しかし記事を出すためにはプロダクトのリリースが必要であり、その都度調整が必要となります。記事の仕上がりの確認もある程度エンジニアが介在しないとできない状況でしたので、記事公開の速度感が低下する要因となっていました。

また先述の通り、記事の機能が追加されるたびに新たなルールが追加されていくため、記事入稿の運用も複雑化していきます。運用に関しても学習コストが増加、また保守性が低下しつつある状態でした。


これらの課題を解消すべく、CMSの導入を検討することとなりました。
CMSに期待したことを整理すると以下の通りです。

  • 独自マークダウン形式の記事管理を刷新し、記事の運用やそれにかかる実装の学習コストを低減、また保守性を向上させる
  • 記事の確認・公開のフローをプロダクトリリースと疎にすることで、プロダクトリリースの負荷を低減、また記事公開の速度感を向上させる

CMS導入における論点

CMSが導入された世界線に想いを巡らせながら検討を始めたわけですが、その道のりはそれなりに泥臭いものでした。導入フェーズに応じて様々な観点での議論をしてきましたが、それらのうち以下を今回紹介します。

  • CMSの選定について
  • フロントエンドの技術選定について
  • APIキーの秘匿について

CMSの選定について

CMSは大きく分けてオールインワン型とヘッドレス型の2種類の形式があります。オールインワン型は記事のデータとUIの両方をCMSで管理・編集でき、ヘッドレス型は記事データのみCMSで管理・編集しAPIでそのデータを提供します。また、それらの実現方法としてOSSを利用しての内製、あるいはフルマネージドのサービスを利用が挙げられます。

これらの選定にあたっては多様な観点での検討が必要になります。エンドユーザーのUXはもちろんのこと、マーケティングに関係する機能は網羅されているか、入稿体験に問題はないか、機能の追加開発しやすいか、セキュリティ性に問題がないか、などなど・・

今回はこれらの観点の洗い出しと意思決定を行うためにCMS選定表を作成しました。


CMS選定表の抜粋

表を作る上で意識的に行ったことは、各観点がMust事項かwant事項かを明示すること観点に順位をつけないことです。順位をつけずMust事項が網羅できているかで選ぶことで、スムーズに選定が進められたと思います。順位をつけないテクニックは輪読会で読んでいた『ソフトウェアアーキテクチャの基礎』にも書かれていたものですが、うまく活用できたと思います。

今回決め手になった観点は以下の通りです。

  • 機能拡張が必要になった際に、属人的にならない開発体制が組めること
  • セキュリティを担保してくれること
  • 既存の記事を一括移行できるような手段(APIなど)が設けられていること

開発観点でヘッドレスCMSを、セキュリティ観点でフルマネージドサービスを選び、
記事の一括移行APIで記事が移行できるヘッドレスCMSサービスとして、最終的にmicroCMSを選定しました。
https://microcms.io/

フロントエンドの技術選定について

今回CMSの導入にあたり、CMS用のフロントエンドのリポジトリも新規に爆誕させました。
生まれたてのリポジトリを見ると愛着がわきますね。

CMSによる記事はいずれも静的なページなので、これまでと同様にSSGで静的記事を生成、S3とCloudFrontで配信します。このSSGを行うフレームワークは、Next.jsではなくGatsbyを選定しました。
https://www.gatsbyjs.com/

Gatsbyではインクリメンタルビルドの機能により、前回のビルド結果の差分を検出して必要なページのみビルドすることが可能です。自社記事の総数はかなりの数となっており毎回全てビルドし直すとなるとビルドリソースも時間もかかるため、この機能は必須事項でした。

また、まっさらな状態から作り始められるということはこれまでに扱ったことのない技術を試せる絶好の機会でもあります。ローカルで軽く試すレベルではなく、実業務に乗せる規模感で技術的知見をためることができるため、大変貴重なタイミングです。この観点で、CSSライブラリはIVRyプロダクトで使っているChakraではなくLinariaを選定しました。

APIキーの秘匿について

CMSを運用に載せるにあたっては、記事入稿時の確認用にプレビュー画面を用意する必要があります。このプレビュー画面は下書きのデータを即時反映させる必要があるため、静的なページではなく動的にmicroCMSの下書きデータを取得する必要があります。プレビュー画面の実装イメージは以下の記事が参考になるのでご参照ください。
https://blog.microcms.io/gatsby-preview/

ここで問題になったのが、APIキーの秘匿です。microCMS上のデータを取得する際はmicroCMSから払い出されるAPIキーを使いますが、これを公開してしまうと悪用のリスクがあるため秘匿しなければなりません。ですので基本的にサーバサイドでの利用にとどめる必要がありますが、先述の通りプレビュー画面では動的にmicroCMSの下書きデータを取得するため、クライアントサイドにAPIキーを置く必要があります。このためプレビュー画面は外部に公開せず社内に限定する機構が必要となりました。

これに対する今回の対応ですが、SSGでプレビュー画面を含む記事ページを生成しているため、物理的にファイルを切り出すことが可能です。プレビュー画面のファイルは検証環境のS3にのみ配置し、本番環境のS3には配置しないようにすることでAPIキーを秘匿する構成としました。

構成と運用

以上の内容も踏まえつつ設計したCMSの全体構成は以下の通りです。

CMS記事のデプロイフローは以下の3種類となっており、それぞれの内容について説明していきます。

  • 検証環境デプロイ
  • 本番環境デプロイ
  • 記事公開

検証環境デプロイ

開発側が新規CMS記事を追加したり既存CMS記事の機能追加・改修をした場合に、その動作確認を行うためのフローです。

  1. GitHub Actions(以降GHA)の検証用ワークフローを実行
  2. GHA上でGatsbyにて静的ファイルが生成され、記事ページが検証環境のS3に格納される
  3. CloudFrontのキャッシュが削除される
  4. 開発QAが検証環境で記事ページを見れる状態になる

上記2のGHA上での記事ページ生成のタイミングで、microCMSの記事データを取得しています。
また、プレビュー画面は本番で公開している記事の内容と一致させる必要があるため、開発中には更新対象としません。

本番環境デプロイ

開発が完了してその内容を本番リリースするためのフローです。

  1. GHAの本番用ワークフローとプレビュー用ワークフローを同時に実行
  2. GHA上でGatsbyにて静的ファイルを生成され、記事ページが本番環境のS3に・プレビュー画面が検証環境のS3に格納される
  3. CloudFrontのキャッシュが削除される
  4. 記事チェック担当が検証環境でプレビュー画面を、エンドユーザが記事ページを見れる状態になる

本番環境への記事ページデプロイだけでなく検証環境へのプレビュー画面デプロイもこのタイミングで実施し、本番の記事と同一の内容が表示されるようにしています。
エンジニアが実行としていますが、実際はGitHubのリリースノート生成をトリガーとしてGHAを自動実行しています。

記事公開

記事担当者がmicroCMSの管理画面上から記事を公開・非公開にするためのフローです。

  1. 記事担当者がmicroCMS管理画面上で記事を公開/非公開にする操作を行う
  2. microCMSのWebhookが発火し、GHAの本番用ワークフローが実行される
  3. GHA上でGatsbyにて静的ファイルを生成され、記事ページが本番環境のS3に格納される
  4. CloudFrontのキャッシュが削除される
  5. エンドユーザが記事ページを見れる状態になる

microCMSでのWebhookの発火タイミングは細かく設定が可能で、記事の公開・非公開に関連する操作に対して発火するようにしています。また、実行するGHAの本番用ワークフローは、開発リリース時のものと同じものを使用してメンテナンスコストを下げています。

CMSの記事の公開が完了すると、Slackのリリースチャンネルで以下のように通知されます。

こうして記事の確認・公開をエンジニア介在なく爆速で回せる環境が整いました🎉


まだ全ての記事をCMSに移行しているわけはないので当書の記事運用の課題を全て解消できているわけではありませんが、CMSに移行した部分では当初の運用の複雑さはなくなり、速度感も解消しました。実装面でも特殊なルールがなくなったためコードベースの見通しもよくなり保守性の向上が実感できています。

一方で、記事データのスキーマ設計やmicroCMSのメンテナンスなどは難しさを感じることもあります。CMSへの移行がさらに進み規模も大きくなってくると新たな課題が顕在化することも予想されますので、これらについてはまたほどよいタイミングで別の記事に昇華できればと思います。

We Are Hiring!!

最後に、IVRyでは一緒に働いてくれるエンジニアを絶賛募集中です!
ご連絡お待ちしています!
https://ivry-jp.notion.site/IVRy-e1d47e4a79ba4f9d8a891fc938e02271

IVRyテックブログ

Discussion