Next.js + CDN、でSEOサイト構築を行った際にnext/link
の挙動に苦しめられたのでその共有をしたいと思います。
実装構成
今回のケースは以下の構成で発生した件となります。
- CDN: Cloudflare
- Next.js: CloudRun
はじめに前提知識としてnext/link
とCDNキャッシュについて触れておきます。
Next.jsのnext/link
について
Next.jsではサイト内ページ遷移に<a />
タグではなく、next/link の利用が推奨されています。
具体的な利用はリンク先の詳細を見ていただければと思いますが、基本的には<a />
と同じような使い方となります。
next/link
の動作イメージ
next/link
と<a />
ではページ遷移の挙動が異なってきます。
具体的にはそれぞれ以下のような違いがあります。
<a />
の挙動
<a />
タグでのページ遷移はリンク先ページを全て読み込んで最初からレンダリングを行います。
next/link
の挙動
next/link
でのページ遷移はリンク先ページの一部分をjsonファイルとしてapi経由で取得し、共通レイアウト以外の箇所をSPA的に差し替える処理を行います。
next/link
のメリット
上記で説明した違いの影響でnext/link
では以下のメリットがあります。
-
ページ遷移が高速
共通以外の遷移先ページの必要最低限な情報のみを取得して部分的にレンダリングされるため無駄が少なく高速にページ移動が可能となります。 -
共通コンポーネントのstateが保持される
レイアウト側に共通コンポーネントを配置しておくと、そのコンポーネントはページ遷移時も前の状態を保持し続けます。
ドロワーメニューの開閉状態や、ユーザーログイン状態などが保持されるのでSPA的なUIが実現できます。
CDNキャッシュについて
それほど更新が少ないページであればキャッシュを作成し、ユーザーリクエスト時にキャッシュより返すことで高速かつサーバー負荷を下げられるメリットがあります。
キャッシュの作成をCDNと呼ばれるエッジサーバーに配置することで更に高速なレスポンスが可能となります。
CDNキャッシュ利用時のnext/link
の問題点
SEOサイトにはわりと必須になるCDNキャッシュですが、next/link
との併用する場合に以下のような問題点が出てきます。
キャッシュが2系統で作成される
ページ流入形式に応じてデータ取得方法が異なるためキャッシュがそれぞれ経路別に作成される事象が発生します。
-
直接ページにランディングするケース
この場合はページURLをキーにしてキャッシュが作成されます。 -
next/link
でページ遷移するケース
この場合は遷移先ページ情報apiで取得するjsonデータに対してキャッシュが作成されます。
このように経路別にそれぞれキャッシュが作成されてしまうためキャッシュのパージ処理が複雑化するのと、キャッシュのライフサイクルのズレから経路によって更新前のキャッシュが表示されるなどの問題が発生します。
SEO記事のように更新頻度が少ない場合はそれほど影響は出にくいのですが、コンテンツ更新の整合性を求める場合は取り扱いが難しくなるので注意が必要です。
CDNリダレクトが効かなくなる
CDNサービスにはCDN側でリダレクトを行ってくれる機能があります。
この機能はエッジ側でリダレクト処理を行うのでアプリケーションサーバーに負荷をかけずに高速にリダレクトできて便利なので積極的に採用していきたいものになっています。
しかし、next/link
を使うとこのCDNリダレクトが使えなくなってしまいます。
CDNリダレクトはページURLパスをkeyとしてリダレクト処理を行いますが、next/link
の場合api経由でjsonデータを取得し、SPA的にブラウザ側でURL historyを変更するのでCDNリダレクトが反応しなくなってしまいます。
対策としてはCDNリダレクトをやめてアプリケーション側でリダレクトを行う必要が出てきます。
まとめ
Next.jsとCDNの併用はよくある組み合わせかと思いますが実際運用してみると思わぬ落とし穴にハマりました。
今回は結果としてサイトの運用上の都合よりnext/link
の利用を諦めましたが、next/link
にはそれなりにメリットがあるので上記の問題が別の方法で解消するのであれば再度利用したいとは思います。