弊社が運営している「Doctorview」というサイトがあります。こちらのサイトは元々、非エンジニアの方がHTMLを作成し、それをS3に置いて公開していました。今年は、このDoctorviewのコンテンツをより充実させていくという事になり、現状の運用ではカバーしきれないので、CMS化するという話になりました。
本記事では、このCMS化にあたって、技術選定からリリース後の振り返りまでを記載します。
1. 技術選定
CMS化にあたって以下の要望がありました。
- CMS化するが、サイトのレイアウトは基本的に変更なし
- ただ、今後、追加改修は入るので、可能な限りレイアウトは自由に設定したい
- SEOは重要である
- 記事公開前にプレビュー機能が欲しい(公開前にお医者様に確認してもらうため)
- 今後、記事作成は社外の人に頼む可能性もあるが、公開は弊社でのみ実施する
端的にいうと「CMS化したいが、サイトのレイアウトは自由に設定したい」というものでしたので、Headless CMS と Next.js による Jamstack なサイトを作成する事にしました。
以下、選んだ技術です。
microCMS
Headless CMS
として microCMS
を選びました。一番の決め手は日本の会社が運営しており、サービスが日本語表示になっていることです。CMSを使うのは非エンジニアということもあり、日本語は大きな利点でした。また、権限周りもある程度、自由に設定でき、プレビュー機能も実装できるため、求められていた要件を満たしていました。
Next.js と Vercel
Next.js
はSEO(CWV)に強いと聞いていたので、採用致しました。その時に調べた内容は zenn の方に書いております。
https://zenn.dev/fukurose/articles/e15df7129cc421
プラットフォームとしては AWS Amplify
と Vercel
で悩みましたが、Vercel
が推奨するワークフロー DPS(develop preview ship)
がスピード感を持って開発できると思い Vercel
に決めました。
TypeScript
これは導入するか最後まで悩みました。このCMS化対応のエンジニアは私一人だけで、私自身も TypeScript
の実務経験が無かったため、導入して、開発スピードが落ち、納期に間に合わないのは避けたいです。最終的には「導入するのであれば最初から」と自分に言い聞かせて導入に踏み切りました。
2. 自動テストと自動デプロイ
選んだ技術で問題ないかの確認のために、簡単なモックを作成し、microCMS
の使用感も含めて社内確認していた時に、自動テストと自動デプロイの準備をしていました。とはいっても、自動デプロイは Vercel
が自動で実施してくれるので自動テストを動かせればOKです。
自動テストは e2e として cypress
、unit テストとして Jest
を GitHub Actions
で動作するように設定致しました。 e2e の方は、Vercel
のプレビュー環境デプロイ完了通知をトリガーとして、そのプレビュー環境で実行するようにしています。
また、開発ワークフローは GitHub Flow
を採用しました。 Vercel
で運用する場合、このフローが一番マッチすると考えたからです。ただ、GitHub Flow
では main と feature ブランチだけですが、弊社では demo 環境も必要でした。Vercel
は環境とブランチが1対1の関係となっているため、demo環境用のブランチも追加しています。基本的な流れは GitHub Flow
と同じで、main ブランチから feature ブランチを切って、実装を開始する。実装を push した時には、Vercel
がプレビュー環境を自動構築する。プレビュー環境で動作OKならPRをマージすることで、本番環境へ自動反映となります。また、feature が main にマージされ次第、Github Actions
で同じ内容を demo にもマージするように致しました。これにより、常に本番環境と同じ実装となる demo 環境を用意しました。
3. 実際に実装してみて
実装してみて最初に思ったのは TypeScript
は導入して良かったでした。私は性格的に「しっかりと計画を立てて実装よりも、まずは実装してみて、気になれば都度変更する」タイプなのですが、この変更が発生する時に、 TypeScript
が必要な変更箇所を教えてくれるので、変更への心理的不安がかなり減ったと思います。優秀なエンジニアとペアプログラミングをしているような感じでした。「そこを変更したらな、ここも変更しないとね」みたいな。
また、 Vercel
のプレビュー環境もとても役に立ちました。Vercel
は push 毎にプレビュー環境を作成してくれるので、A案とB案どちらが良いか社内確認を取る時にも、簡単に両案のプレビュー環境を用意できます。今回で言えば、CMS化前の Doctorview
では webフォント を 3つ読み込んでいました。ここはパフォーマンス改善のためにも、どれか1つに出来ないかと検討する際、フォントなしと各webフォントを1つだけ読み込んだプレビュー環境を作成し、見た目とパフォーマンスを調べて調査致しました。
結果としては、フォントなしになりましたが、、それも各プレビュー環境での比較があってこそだと思います。
Next.js
も事前に調べていた通り、フロントエンド側のベストプラクティスが詰まったフレームワークで選択して良かったと思います。画像の最適化、(今回は使わなくなりましたが)webフォントの最適化、外部JSの読み込みの最適化などをフレームワークで用意してくれています。ES2020で導入された dynamic import
が使えるのも良かったです。Doctorview
では「他のドクターをお探しですか?」というレコメンド機能があるのですが、こちらは初期表示時には不要なので、 dynamic import
を使って表示することにより、初期ロードの負荷を軽減しています。その他にも無駄なCSSを削除したりなど、パフォーマンス改善には力を入れて対応致しました。その結果もあり、light house のスコアを大幅に改善出来ました!!
逆に上手く出来なかったのは、CSSの箇所です。Next.js
では全ページ共通のCSSはグローバルCSSとして読み込み、その他はコンポーネントレベルでCSSを適用するように推奨しています(Next.jsに限った話ではないですが)。ただ、弊社ではCSSを触るのがデザイナーで、実装に詳しくないデザイナーの方がコンポーネント単位でCSSを設定するのは、難しいと判断しました。特に、変更したいCSSが、どのコンポーネントなのかを判断するのが難しいと考えています。
そのため、コンポーネント単位のCSSはやめて、ページ単位のCSSにしました。使っているのは全ページのCSSとページ別のCSSだけになるので、修正箇所は少なくなります。
- 全ページのCSS:
src/styles
ディレクトリにあるcssファイル - ページ別のCSS:
src/pages/
配下の index ファイルにある<style jsx global>
内
<style jsx global>{`
/* ここにCSSを追記、修正してもらう */
`}</style>
これで、変更するCSSの場所は分かりやすくなりました。ただ、やはり、サイト全体に統一感を持たせるためにも、コンポーネント単位でのCSSを設定したいので、ここは今後、改善出来ればと考えています。個人的には、class名とかを考えるのも手間なので、 CSS Modules
を使いたいというのもあります。
4. 全体を通して振り返り
最初に自動テスト/自動デプロイを作成していたことが、良かったかなと思います。 ここが上手く動作していると、開発サイクルが速く回るので、開発が楽しくなります。実装フェーズでは TypeScript
にチェックしてもらい、実装出来れば push して、自動テストを走らせる。オールグリーンなら、main にマージして本番反映という流れをスムーズに行えるので、より実装に集中することが出来ました。
Vercel
はプレビュー環境作成、自動デプロイという点で素晴らしかったです。 ただ、AWS Amplify
でも同じような事はできるはずなので、(Vercel
に依存しすぎているのも良くないので)今後のため調べておこうと思います。また、GCP
でも同様な事は出来るはずなので、こちらも合わせて調べたいと思います。
全体を通して、今回選んだ技術は上手くマッチしていたと思います。しかし、これが常に正解という訳ではないので、サービスを開始するときは、マッチする技術をしっかりと見極めていきたいです。 また、Doctorview が今後、大きくなっていくと、合わなくなってくる技術も出てくるかと思います。その時は、今の技術に縛られずに、自由に技術選定していきたいです。 その時は、また記事に出来ればと思います。