Slide 1

Slide 1 text

PR TIMESにおける Next.js と cache の付き合い方

Slide 2

Slide 2 text

自己紹介 やなぎ(25歳) PR TIMES 開発部 フロントエンドエンジニア - X(Twitter): @apple_yagi

Slide 3

Slide 3 text

話すこと 1. PR TIMESのNext.js運用構成 2. 3つのキャッシュ戦略 3. Next.jsとの付き合い方 4. まとめ

Slide 4

Slide 4 text

PR TIMESのNext.js運用構成

Slide 5

Slide 5 text

Next.jsの運用構成 引用元:https://developers.prtimes.jp/2023/12/13/replace-press-release-page-with-nextjs/

Slide 6

Slide 6 text

Pages Router or App Router - PR TIMESではPages Routerを使用している - そのため、Next.jsでキャッシュを持つことは一切していない

Slide 7

Slide 7 text

3つのキャッシュ戦略

Slide 8

Slide 8 text

PR TIMESでNext.jsから配信されているページ - トップページ - プレスリリース掲載ページ - キーワード検索ページ

Slide 9

Slide 9 text

PR TIMESでNext.jsから配信されているページ - トップページ - プレスリリース掲載ページ - キーワード検索ページ

Slide 10

Slide 10 text

トップページ(https://prtimes.jp)

Slide 11

Slide 11 text

トップページのキャッシュ戦略 - Cache-Controlヘッダーは no-cache, max-age=0, must-revalidate - ブラウザにはキャッシュを持たせない - ただBFCacheは有効にしたいので no-store はつけない - Surrogate-Controlヘッダーは max-age=5, stale-while-revalidate=10 - Surrogate-ControlヘッダーはFastly独自のヘッダーで Cache-Controlと同じ内容を渡すことができる - FastlyはCache-ControlよりもSurrogate-Controlを優先し、Fastly にのみキャッシュが保存される

Slide 12

Slide 12 text

キャッシュTTLの設定について Surrogate-Control: max-age=5, stale-while-revalidate=10 - キャッシュは最大で15秒しか保持しない - max-age=5:5秒間はキャッシュを返す - stale-while-revalidate=10:5秒が過ぎた後の10秒間は古いキャッ シュを返しつつ、新しいキャッシュを生成する

Slide 13

Slide 13 text

なぜ15秒しか保持しないのか PR TIMESのトップページには新着プレスリリースが表示されており、プレス リリースが配信されたら、できるだけ速く反映したい

Slide 14

Slide 14 text

キャッシュTTLが1つのコンテンツに引っ張られる問題 プレスリリースのランキングなど、データの更新頻度があまり高くない箇所も APIからデータを取得しHTMLを生成する必要がある 更新頻度:低 更新頻度:高

Slide 15

Slide 15 text

App Routerを使うことで解決できそう App Routerでコンポーネントをキャッシュをすることで解決することができそう - use cacheディレクティブ良さそう ただApp Routerがキャッシュを持つのは考えることが多い - self hostingの場合、Next.jsのキャッシュをどこに置くかが難しい - 多段キャッシュになり挙動を正確に把握するのが困難になり、キャッシュを 簡単に削除することができなくなる - キャッシュは単一の箇所で行いたい(PR TIMESでいうとCDN層)

Slide 16

Slide 16 text

そもそもトップページのキャッシュヒット率は良い - キャッシュヒット率は90 ~ 99%で推移 - Lighthouseのパフォーマンスは100%(キャッシュHit時/通信環境による)

Slide 17

Slide 17 text

トップページのキャッシュ戦略まとめ - キャッシュTTLは短め(最大15秒) - ただキャッシュヒット率は良い - URLが単一( https://prtimes.jp )でかつ、リクエスト数が多 いからと考えている - パフォーマンスも良い - 90%以上のリクエストをCDNで返せているため

Slide 18

Slide 18 text

PR TIMESでNext.jsから配信されているページ - トップページ - プレスリリース掲載ページ - キーワード検索ページ

Slide 19

Slide 19 text

プレスリリース掲載ページ

Slide 20

Slide 20 text

プレスリリース掲載ページのキャッシュ戦略 - Cache-Controlは no-cache, max-age=0, must-revalidate - トップページと変わらずブラウザキャッシュはしない - Surrogate-Controlは max-age=60, stale-while-revalidate=120 - 最大で180秒キャッシュを保持する

Slide 21

Slide 21 text

キャッシュTTLについて - 一度配信されたプレスリリースの更新頻度はとても少ないが180sと短い - プレスリリースが更新された時にキャッシュをパージする処理をして いないため、更新された時のことを考えてこの設定にしている - 今後はプレスリリース更新時にCDN(Fastly)のキャッシュをパージする 処理を追加し、キャッシュTTLを伸ばす予定 - Fastlyのキャッシュパージは高速(Instant Purge) - 150ms以内にグローバルに分散されたキャッシュを削除できる - また実行回数による課金はなく、回数制限もない

Slide 22

Slide 22 text

キャッシュヒット率とパフォーマンス - キャッシュヒット率は26 ~ 56%で推移 - Lighthouseのパフォーマンスは95%

Slide 23

Slide 23 text

プレスリリース掲載ページのキャッシュ戦略まとめ - キャッシュTTLは180秒 - URLがプレスリリースによって異なるため、キャッシュヒット率は トップページより低い - キャッシュヒットした時のパフォーマンスは良い - 今後キャッシュTTLを伸ばし、キャッシュヒット率の改善を行う予定

Slide 24

Slide 24 text

PR TIMESでNext.jsから配信されているページ - トップページ - プレスリリース掲載ページ - キーワード検索ページ

Slide 25

Slide 25 text

キーワード検索ページ

Slide 26

Slide 26 text

キーワード検索ページのキャッシュ戦略 - Cache-Controlは no-cache, max-age=0, must-revalidate - 変わらずブラウザキャッシュはしない - Surrogate-Controlは設定していない

Slide 27

Slide 27 text

なぜキーワード検索ページはキャッシュしないのか - 検索するキーワードが完全一致することは多くないと想定している - https://prtimes.jp/main/action.php?run=html&page=searchkey &search_word=PRTIMES - キャッシュをするとしても1分程度を考えているため、1分間の間に何 回同じキーワードが検索されるか?を考えるとする必要がなさそう

Slide 28

Slide 28 text

パフォーマンス - Lighthouseのパフォーマンスは100% - キャッシュがなくてもそもそもパフォーマンスが良かった

Slide 29

Slide 29 text

パフォーマンス以外でのキャッシュの有効性 - オリジンサーバーへの負荷を軽減 - リクエストを前段のCDNで返すことにより、そもそもNext.jsにリク エストを到達させなくできる - プレスリリース掲載ページはSNSからの流入で急激に高負荷になるこ とがあるため(バズった時)、キャッシュを用いてアクセスを捌く必 要がある

Slide 30

Slide 30 text

Next.jsとの付き合い方

Slide 31

Slide 31 text

Next.jsの機能をほぼ使っていない - getServerSidePropsのみしか使っていない - LinkコンポーネントやuseRouterなどは使わずにハードナビゲーション を行っている - PR TIMESはパフォーマンスが良いため、ハードナビゲーションでも 問題ない - また、ソフトナビゲーションを行うとFastlyでキャッシュをパージ するときに問題が発生する可能性がある - next/imageも使用しておらず、FastlyのImage Optimizerで画像の最適 化を行っている

Slide 32

Slide 32 text

Next.jsに求めているもの - 開発者体験(DX)の良いテンプレートエンジン - Reactをサーバーでレンダリングしてくれる、それだけで良い - とは言いつつ、zero configやFile-Based Routingは嬉しい - キャッシュはFastlyでやるのでwebpackをどうにかしてくれると。。 - Viteを使いたいのでReact Router v7(Remix)に移行しようか迷っ ている - ずっとPages Routerを使い続けるのは。。

Slide 33

Slide 33 text

まとめ

Slide 34

Slide 34 text

まとめ - Next.jsをセルフホスティングで運用しFastlyでキャッシュを行っている - キャッシュ戦略はページの特性によって都度変えている - CDNのキャッシュだけでも高パフォーマンスで高負荷に耐えることができ る - Next.jsの機能は最小限の利用に留めつつ、他のフレームワークへの乗り 換えも検討している