WebサイトをWordpressからNext.js + MicroCMSに置き換えた話

この記事はMIERUNE Advent Calendar 2021 3日目の記事です。今回はGISに絡んだ記事ではなくMIERUNEのWebサイトは9月にリニューアルをおこなったのでその裏側的な記事になります。

## はじめに
9月にMIERUNEのWebサイトはリニューアルを行いました！
WordPressからNext.jsへの変更があったり、デザインが大きく変わっていたりと全面的なリニューアルとなりました。
FCP・LCPなどのページスピード的な部分や、どの端末でも不快感なく閲覧できるようレスポンシブへの対応などなどこれまでのサイトよりもユーザーにとって閲覧しやすくというところを意識して制作をしています。
今回はそのWebサイトリニューアルの技術的な部分をご紹介しようと思います。
※今回は実際のコードなどは登場しません

## 使用技術・利用サービス(12/2現在)
- Next.js (v11)
    - 依存ライブラリ
        - Pathpida
            - ルーティング・静的コンテンツ管理のため
        - Maplibre GL JS
            - 地図表示用
        - React Hook Form
            - フォーム制御
        - Swiper
            - indexのカルーセル用
        - MicroCMS JS SDK
            - MicroCMSのコンテンツ取得のため
    - 開発効率化のための依存ライブラリ
        - Sass
            - Scss ModuleでCSSを記述するため
        - ESLint
            - Typescript / HTML のLinterとして
        - Prettier
            - Formatterとして
        - StyleLint
            - SCSSのLinterとして
        - TypeScript
            - JSXをTypeScriptを使って型付けしているため
- MicroCMS
    - ニュース等のコンテンツ管理のため
- Amplify
    - 本番環境のデプロイ・開発時のプレビューのため


## これまで
WordPressを利用して横スクロールのWebサイト
![旧Webサイト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/aba16983-7b78-133a-fdaa-73c4b1795e57.png)

### 問題点
 - FCP / LCP共に遅く、表示までにすくなくとも5秒以上かかっていた。
 - アニメーションを多用していて、クリックからコンテンツ表示に時間がかかり閲覧性はあまり良くなかった
 - 横スクロールかつページネーションだったため一気にみるようなことができない

### よかった点
 - デザイン（特にトーン・カラー・コンポーネントなど）はとても会社にマッチしていた
 - 全体のコンテンツ量もちょうど良い
 - WordPressのためニュースなどもある程度書きやすくはあった。

## 今回
MicroCMS + Next.jsで縦スクロールのWebサイト

![新Webサイト](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/84d5ac39-588f-ea5b-042f-5885a3008c19.jpeg)

### 改善点
- 表示速度の改善
- アニメーションの量の低減
- ユーザーのクリック・スクロール等のイベントとの時間的なずれの削減
- WordPressからMicroCMSに移行する
- Amplifyを用いてCI/CDを整備する

という感じです。さて、ここからは改善点をそれぞれ細かく見ていきます。

### 表示速度の改善
まずはLightroomのスコアを見てみましょう
旧HP
![スクリーンショット 2021-02-01 16.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/d6392ff5-77a7-96e8-7a07-c5b9d2030bc2.png)
新HP
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275457/6d23a352-d1bd-aec2-fc7b-b54f8b6576a1.png)

約12点ほど上がってますね。
Metrics(各種指標)についても見ていきます。

- FCP(最初のコンテンツが描画されるまでの時間) : -0.2s
- Speed Index(ロード開始からファーストビューの時間) : -1.8s
- LCP(最大コンテンツの描画) : -0.5s 
- TBT(FID, 初回描画から操作可能になるまでの時間) : -130ms 
- TTI(レイアウトが安定して操作が適切に行えるまでの時間) : -1.4s
- CLS(累積レイアウトシフト) : -0.012

全ての項目で減少しています。
この中でWeb Core Vitalに該当するLCP, FID, CLSは全項目GoodになっておりSEO的にも良好になりました。
体感速度も実際向上しています。（旧HPを触っていただけないのが残念ではありますが...）

この部分はNext.jsの自動最適化が大きく寄与しています。
API Routeを使っていたり、一部 `next/image` にて画像最適化をおこなっている関係で今回はAmplify上にNext.jsをデプロイしていますが、完全な静的サイトにできたらさらに早くなるかもしれません。
(Amplifyに関しては後ほど...)

### アニメーション量の低減
一部のコンポーネント（ボタンやナビゲーションなど）の多少の動きがあるものに関しては短めのtransitionを設定することで急に変化することは避けながらも不必要に長く、イライラするアニメーションはないようにしています。

### ユーザーのクリック・スクロール等のイベントとの時間的なずれの削減
私はクリック・スクロールなどをおこなった後その反応までに少しでも時間がかかると違和感があってモヤモヤするためその部分もなるべく少なくなるようにしています。

SSG・Preloadを利用して遷移先の読み込みの高速化やアニメーション量の低減によってなるべくずれがないようにしています。

### WordPressからMicroCMSに移行する
これまでWordPressを利用していたことは最初にも書きましたが、今回移行先のCMSとしてMicroCMSを選定しました。日本語のUIがしっかりと整備されており、JavaScriptのSDKも用意されているため今回はSDKにTypeScriptを用いて型を与えて利用しています。
WordPressからMicroCMSへの移行はWordPressからMarkdownのファイルをExportすることができるわけではないため、移行記事かどうかのフラグをつけ移行記事の場合はそのままHTMLをレンダリングするようにしています。

また、Tech/Devのページなどの各情報も一部MicroCMSに格納しています。

### Amplify を用いてCI/CDを整備する
LinterやFormatter, TestなどPR時に行うチェック類を除いてデプロイなどはAmplifyを利用しています。
AmplifyはNext.jsを公式にサポートしていますが、ISRやgetStaticPathsのfallbackなど一部機能が正常に利用できません。(10月時点)
これはServerless Next.jsを利用した場合も同様の状態に陥っていたため内部的にServerless Next.jsを利用していることによるものだと思われますが真相はAWS様の中...

ただ、API Routeや `next/image` の自動最適化などの基本的なものは動くためAmplify上にデプロイしています(今ならCloud Run + Cloud CDNなどでもいいのかもしれませんが)

## おわりに
Next.jsという素敵なフレームワークのおかげもあり無事Webサイトのリニューアルを終えることができました。
当初からパフォーマンスの改善、ユーザー目線で見やすいサイトにというところにフォーカスを当ててリニューアルを進めてきていましたので、実際目に見えるレベルで大きくページパフォーマンスが改善し快適に閲覧できるようになりとてもよかったです。

[MicroCMSのプラン改定](https://microcms.co.jp/news/20211129-01/)が予定されていることもあり、今後MicroCMSを利用したブログやWebサイトが増えていくのではないかなと思っています。


# おまけ
MIERUNEでは世界に挑戦する仲間を募っています。
あなたの技術や経験を活かしてみませんか？
ご興味あるかたは、ぜひご連絡下さい。

https://www.mierune.co.jp/recruit