Next.jsのIncremental Static RegenerationでWordPressをHeadless CMSとして使ったら成功したけど失敗した話

# TL;DR
非エンジニアが管理してるWordPressをHeadless CMSとして扱いNext.jsのガワで表示したら運用にマッチしなかったので元に戻した

# 概要
WordPressやPHPで作られたコーポレートサイトのリニューアルをNext.js on Vercelで行った
その中に「ニュース」「ブログ」「ご利用ガイド」のようなWordPress記事群があり、WordPressの[REST API機能](https://ja.wp-api.org/) でビルド時にJSONデータだけ取得し、Next.jsの [Incremental Static Regeneration](https://nextjs.org/blog/next-9-5#stable-incremental-static-regeneration)でラップして表示する方針にした
justincase.jp ドメイン上にあったWordPressは、そのドメインをVercelに扱わせることで共存できなくなったため、別ドメインへ引っ越した

# 得られたメリット
- 差分管理が不完全でいつ壊れるか分からないWordPress上のコードをほとんど使わなくして、Git管理されたコードで運用可能になった
  - モダンでないhtmlの書き方やライブラリを使わず、lint管理されたhtml+cssでページを作れた
- プロジェクトがブランド イメージ刷新であることから重要であった、デザイナーの新しいデザインを忠実に再現できた
  - WordPressの記事も、他ページと共通のヘッダー・フッターを表示できた
- 各WordPressを置いていたサブディレクトリ(/blog などのような)URLにコンテンツを表示するような状態を保持できた
- Incremental Static Regeneration自体の効果
  - WordPressサーバーへの負荷を抑える・表示の爆速・1分（ここは任意）以内に記事更新も反映されること の両立
      - 巷にはキャッシュのバックエンドを頑張る記事が散見されるが、これだと完璧じゃないもののWordPress REST APIが遅いことを楽に9割がた回避できる
  - ビルド時間もCIでは増えないので、大量のコンテンツをSSGする際の問題となるデプロイが遅くなる問題が回避できる
- プロジェクト参画時に「WordPressをなるべくなくしたい」という意向を受けていたので、WordPressをHeadless CMSとして使うことで別のに移行してもCSSをあまり変えず移行しやすい状態にはできた

# デメリット

## 予想済みだったが予想以上にダメだったデメリット
- WordPressのプレビューを諦めた結果、記事執筆者が最終的な見た目を直接確認できないこと。及び、それを見せてOKを出すレビュワーとのやり取りも崩れたこと
  - Next.jsの[Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode) を使ってプレビューする運用も計画していたが、そこまでの工数をとれなかった
- 些細なことも全部エンジニアに依頼が来るようになった（WordPressを触れる一部の非エンジニアが触れる部分がなくなったので）

## 予想済みで何とかなりそうだったデメリット
- 記事のCSSをベストエフォートで（見た目に重要なhtmlタグだけ）スタイリングすることになるので、考慮していないHTMLタグなどがあると崩れて対応が必要になる
- クエリパラメータによる記事検索ページをIncremental Static RegenerationでなくSSRするしかなかった
  - `getStaticProps` などビルド時の関数が任意のslugのpathに対してIncremental Static Regenerationを設定できるのにqueryを取得できない仕様のため、queryに対してはIncremental Static Regenerationを設定できないため
  - （Incremental Static Regenerationの仕組み自体が実際は静的じゃないのだし、どっちも実行時にしかわからんのだからqueryに対しても書けるようになってくれ…）

## 予想してなかったデメリット
- 記事のYouTubeリンクなどを貼るだけだと勝手にdata-iframeなタグになってしまい、REST APIのrenderedなhtml文字列のみでは再現できないので、動画はiframeを直接書いて埋めてもらう必要が生じた
  - WordPress OEmbed の仕組みか何かのせい…？
- 特定のプラグインがなぜかREST APIのデータを虚無に破壊してページが表示できなくなる場合があることが分かったし、今後運用者が何をインストールしていつREST APIが壊れるか分からない危険性があった
  - 例: WP User Avatar
  - しかもNext.jsのビルドフローとしては、ビルド時にWordPressデータ取得できないとビルドがエラーで停止するので全てのページのリリースに影響がある
- `lang=en` のようなクエリつきの記事ページが存在することをリリース後に知り、先にも書いたようにIncremental Static Regenerationがクエリに対応してないので、運用を保つならSSR+CSRするしかなさそうだった

# 運用面の不満は自明じゃないか。なんでそんなことになった？
色々なプロジェクト運営上の不備のため、関係者としっかり話し合って事前にユーザーテストできなかったので自明じゃなくなり、リリース後の問題噴出を招きました
また、もっとリリース後のサポート工数が取れると思っていたが、そうでなくなったことが問題になってきました

# 最終的に何をしたか
- WordPressをHeadless CMSとしてNext.jsでラップすることを基本的にやめた
  - WordPressインスタンスをサブドメインに移植し、元々の運用のように そこにWordPressをそのまま表示するようにし、旧URLはそちらへリダイレクトする
  - デザイナーのデザインを極力再現すること、共通ヘッダー・フッター、サブディレクトリ方式、などの要件を諦めて緩めた
  - つまり、先に上げたメリットを捨ててデメリットを解消した
- ちなみにNext.jsの[Rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites) 機能を使うとサブディレクトリのURLに別ドメインのWordPressを表示できるので、WordPressをそのまま表示する条件まで緩めたときに採用を検討したが、以下の理由で採用しなかった
  - Next.jsへ移行する途中に一時的に使うのが主な想定のようであること
  - 同じページを表示できる全く別の正しいURLが2つになってしまうのがSEO上よくなさそうであること（ `<link rel=”canonical”>` などがあるとはいえ）


# 共有したい学び

## 技術的な学び
- 非エンジニアが複雑に運用しているWordPressの扱いをHeadless CMS化するべきではない
  - プレビューは何より大事
  - ほとんどの要件や技術者の考えるほとんどの利点より、記事運用者のシンプルな運用の方が重要なので守るべきだった
- **おそらく、移行して良いのは以下の場合**
  - **自分だけ、もしくは前後の運用をよく分かっているエンジニアだけで運用している**
  - **エンジニアが潤沢に工数を確保して、リリース後の運用をサポートできる**
- WordPressのREST APIはあまり使いやすくない
  - プラグインや設定やなんやのせいでデータが変わったり壊れたりするのも危ない
- Incremental Static Regenerationは素晴らしい
  - 一部のページにWordPressの記事最新3件を表示するため、などの用途で、まだ有用に使っている

## 失敗の間接的原因だったプロジェクト上の学び
- プロダクトオーナーとかディレクターをちゃんと決めるべき
- デザイナーのデザインが関係者OK貰っているかどうか確認するべき
- リリース後に知った重要な仕様があったので、事前に現状の運用を細部まで聞き込みするべき
- 運用を変える重要な方針の確認はSlackのメンションで済ませずにミーティングを開くべき
  - Slackで済むならミーティングを減らせる、と思って削ったのは間違いだった
  - 関係者が多いほど、無意識にスルーするか、最後まで読まれない
      - 特にChannelメンションのとき、自分宛てだという意識は薄れる
      - 特にリンクは読まれにくいっぽい
  - メンションの回数もあまり意味がない