Slide 1

Slide 1 text

より速い WEB を目指す Next.js 【Next.js Update!】 v12リリースを踏まえ、Next.jsの採用を考える

Slide 2

Slide 2 text

吉井 健文 / Takepepe 株式会社リクルート  APソリューショングループ フロントエンドエンジニア・アーキテクト

Slide 3

Slide 3 text

Agenda ■ 前半:Next.js Conf 2021 おさらい / ■ 後半:Next.js 12 発表をうけて ■ Static x Dynamic ■ React Server Components x Edge ■ Next.js x Granular Renderings ■ Next.js x Granular Prefetch ■ Next.js x Granular Chunks

Slide 4

Slide 4 text

Next.js Conf 2021 の発表 Next.js Conf 2021 における発表内容は、 Next.js・React 開発の転換期到来アナウンスとなりました。 現時点では実験的な機能(beta / alpha版)が多いですが、 その発表内容は大きなインパクトがありました。

Slide 5

Slide 5 text

Next.js Conf 2021 の参考資料 Next.js at the Edge - Suzanne Aldrich + Lee Robinson - (Next.js Conf 2021) https://www.youtube.com/watch?v=WlP2TB2ORL4 Blog - Next.js 12 https://nextjs.org/blog/next-12 前半36Pまでは、上の動画内容をおさらいします

Slide 6

Slide 6 text

Static x Dynamic

Slide 7

Slide 7 text

Next.js の歴史 Server-Side Rendering SSR Automatic Static Optimization Static Site Generation SSG Incremental Static Regeneration ISR Next.js は SSR framework としてスタート。

Slide 8

Slide 8 text

Next.js の歴史 Server-Side Rendering SSR Automatic Static Optimization Static Site Generation SSG Incremental Static Regeneration ISR 続いて、Automatic Static Optimization を導入しました。

Slide 9

Slide 9 text

Next.js の歴史 Server-Side Rendering SSR Automatic Static Optimization Static Site Generation SSG Incremental Static Regeneration ISR Static Site Generation を採用し、Hybrid Framework に。

Slide 10

Slide 10 text

Next.js の歴史 Server-Side Rendering SSR Automatic Static Optimization Static Site Generation SSG Incremental Static Regeneration ISR ISR を採用し、リビルド不要でページ更新を可能に。

Slide 11

Slide 11 text

Next.js の歴史 Server-Side Rendering SSR Automatic Static Optimization Static Site Generation SSG Incremental Static Regeneration ISR ページ単位で「きめ細かい (Granular) 」戦略を取れる仕組みを提供しました。

Slide 12

Slide 12 text

Static vs Dynamic これまで Next.js が提供してきたソリューションで明るみになったのは ■ Static(getStaticProps / getStaticPaths) ■ Dynamic(getServerSideProps) この両者が、スピードとパーソナライズで対立していることでした。

Slide 13

Slide 13 text

Static vs Dynamic SSR (動的) はリクエスト毎に HTML を算出しコンテンツをパーソナライズ。 Dynamic (Personalization) Static (Speed) SSR

Slide 14

Slide 14 text

Static vs Dynamic しかし、一貫したパフォーマンス提供が困難でした。 Dynamic (Personalization) Static (Speed) SSR

Slide 15

Slide 15 text

Static vs Dynamic SSG (静的生成) は Edge CDN キャッシュから静的配信し、高速な提供を実現。 Dynamic (Personalization) Static (Speed) SSG

Slide 16

Slide 16 text

Static vs Dynamic しかし、リクエストに基づき HTML を変えるパーソナライズが失われました。 Dynamic (Personalization) Static (Speed) SSG

Slide 17

Slide 17 text

この両者の強みを同時に発揮できるものとして Dynamic (Personalization) Static (Speed) Static x Dynamic =

Slide 18

Slide 18 text

Static x Dynamic = Edge Next.js が選んだのが Edge というソリューションです。 Edge Dynamic (Personalization) Static (Speed)

Slide 19

Slide 19 text

Static x Dynamic = Edge USER ORIGIN Edge (Computing) は CDN と同様に、ユーザーとオリジンの中間に位置します。 Edge

Slide 20

Slide 20 text

Static x Dynamic = Edge USER ORIGIN この Edge で処理する仕組みとして middleware (beta) が導入されました。 Middleware

Slide 21

Slide 21 text

Static x Dynamic = Edge middleware はリクエストに基づき、オリジン到達前にコードを実行します。 Middleware

Slide 22

Slide 22 text

Static x Dynamic = Edge 書き換え(Rewrite) / リダイレクト(Redirecting) / ヘッダーの追加(Header) Middleware

Slide 23

Slide 23 text

Static x Dynamic = Edge さらには HTML のストリーミング(Streaming) Middleware

Slide 24

Slide 24 text

Static x Dynamic = Edge 物理的にユーザーに近いサーバーで Edge 関数を実行できます。 Middleware

Slide 25

Slide 25 text

No Cold Starts, 100x Faster middleware は Vercel Edge Functions という厳密なランタイムで実行されます ■ V8 を使用した JavaScript & WASMエンジンで構築されている ■ fetch 関数など、標準の Web API ※ に限られる ■ Native Node.js API はサポート外(fs等) ■ Native Node.js API に非依存の node_modules は利用可 ※ 標準の Web API:ESM、Fetch、Stream、AbortController、など。 Web上のサービスが提供する RESTやGraphQL APIのことではない 【詳細】Edge Runtime https://nextjs.org/docs/api-reference/edge-runtime

Slide 26

Slide 26 text

No Cold Starts, 100x Faster この制限のある環境下において、 仮想マシン or コンテナで起動する Node.js よりも 100倍高速な起動を提供することが可能になっています。 100 x Faster

Slide 27

Slide 27 text

No Cold Starts, 100x Faster middleware で可能な一例に、以下の機能が挙げられます ■ Authentication ■ Bot Protection ■ Redirects ■ Browser Support ■ Feature Flags ■ A/B Testing ■ Server-Side Analytics ■ Logging

Slide 28

Slide 28 text

No Cold Starts, 100x Faster 例えば geo location に応じ、 静的ページを出し分けることが 可能になります。 【詳細】Next.js at the Edge https://youtu.be/WlP2TB2ORL4?t=368

Slide 29

Slide 29 text

No Cold Starts, 100x Faster middleware はセルフホスティング環境であっても、 Next.js の標準的なビルドで利用可能に(Node.js の sandbox 内)※ Vercel にデプロイする場合、middleware は Edge に展開。 開発者はインフラ構成を気にすることなく、 デフォルトでこの機能が有効になります。 ※ セルフホスティング環境では「 No Cold Start, 100x Faster」にはなりません

Slide 30

Slide 30 text

React Server Components x Edge

Slide 31

Slide 31 text

React Server Components x Edge Next.js Conf 2021 で最大の驚きは(少なくとも私は) React チームと協力し React 18 サポートの準備を開始したこと、 そして React Server Components(aplha版)が Next.js で利用可能になるという発表です。 ※ React Server Components サポートは、React 18 サポートより未来になる認識 ※ React Server Components サポート時期について言及: https://github.com/reactwg/react-18/discussions/37

Slide 32

Slide 32 text

React Server Components x Edge 従来 SSR (getServerSideProps) での課題 ■ データ取得完了まで、レスポンスを返却できない ■ サーバーからのレスポンスを待つ間、真っ白な画面が表示される ■ 全ての HTML が表示されるか否か

Slide 33

Slide 33 text

React Server Components x Edge React Server Components x Edge で得られるメリット ■ Edge 関数から即座に Streaming が開始されるため、待つ事がない ■ 段階的にレンダリングを行い、完了したものから Streaming ■ ブラウザ向け JS が最小限に、インタラクティブになるまでが高速に ■ サーバー側で計算するため、非力なデバイスでも高速に

Slide 34

Slide 34 text

React Server Components x Edge で得られるメリット ■ Edge 関数から即座に Streaming が開始されるため、待つ事がない ■ 段階的にレンダリングを行い、完了したものから Streaming ■ ブラウザ向け JS が最小限に、インタラクティブになるまでが高速に ■ サーバー側で計算するため、非力なデバイスでも高速に TTFB/ LCP/ FID など、Web Vitals 向上に貢献 React Server Components x Edge

Slide 35

Slide 35 text

getServerSideProps / getStaticProps は将来不要に ■ データフェッチ関数をコンポーネントと同じ場所に配置可能になる ■ 必要に応じて最小限のスクリプトが送られ、段階的に Hydrate される ■ 将来的に ISR の様な、ページ単位のキャッシュは必要なくなる ■ その代わりに「コンポーネントレベル」で詳細なキャッシュが可能になる React Server Components x Edge

Slide 36

Slide 36 text

granular component caching という展望 ■ Suspense 境界のように機能する「Data」コンポーネントを検討している ■ コンポーネント単位で surrogate keys を発行し個別でパージ可能に ■ コンポーネント単位で revalidate 秒数指定が可能に ■ React Server Components と Edge functions のイノベーションで可能になった React Server Components x Edge

Slide 37

Slide 37 text

Next.js Conf 2021 感想

Slide 38

Slide 38 text

Next.js Conf 2021 感想 発表は未来的で、驚きの多い内容でした。しかしながら、 実験的な内容ばかりで「実務ですぐに使える内容ではなさそう」 という感想を持った方も多いと思います。 そもそも、React Server Components を使う理由に、 いまいちピンと来てないかもしれません。

Slide 39

Slide 39 text

まず、なぜ React や Next.js を使うのか、 明確な動機を考えてみましょう。 開発者体験でしょうか? それとも、要件に適合させやすい Hybrid な柔軟さでしょうか? いずれも正しいと思います。 Next.js Conf 2021 感想

Slide 40

Slide 40 text

ひとつは、誰もがすぐに開発を始められることです。 Dan Abramov 氏が Create React App 発足の動機として語る様に、 過去、フロントエンド開発環境の準備は敷居が高いものでした。 Next.js Conf 2021 感想 Before CRA, the ecosystem was hopelessly fragmented. The entire category of tools like this didn't exist — there was no Next or Gatsby or Vite and so on. The vast majority of React developers were setting up their Babel, webpack, etc, manually, and having a really bad time. These tools were difficult to get working together correctly. ” ※ 引用:https://github.com/facebook/create-react-app/issues/11180

Slide 41

Slide 41 text

Next.js Conf 2021 感想 今日、Next.js / Gatsby / Vite を利用すれば、あまり意識せずとも、 フロントエンド開発のベストプラクティス恩恵を、 開発初期から受けることができます。 ※ 引用:https://github.com/facebook/create-react-app/issues/11180 Before CRA, the ecosystem was hopelessly fragmented. The entire category of tools like this didn't exist — there was no Next or Gatsby or Vite and so on. The vast majority of React developers were setting up their Babel, webpack, etc, manually, and having a really bad time. These tools were difficult to get working together correctly. ”

Slide 42

Slide 42 text

最も着目すべきは、React や Next.js が 「Web Vitals」を指針に、 「ユーザー体験向上を中心に進化」している点です。 React Server Components x Edge も 例外なくこの取り組みの一環だと思います。 Next.js Conf 2021 感想 ※ 引用:https://web.dev/vitals/

Slide 43

Slide 43 text

Next.js Conf 2021 のデモにあったとおり、 React Server Components は HTML と 最小限の JavaScript しか届けません。 細切れな生成済み HTML を段階的に hydrate するため、 低スペック端末でも快適な UX の提供が期待できます。 Next.js Conf 2021 感想

Slide 44

Slide 44 text

React Server Components の恩恵が受けられると想定できるのは、 「処理速度・ネットワークが遅い」モバイル端末です。 (表示すべき HTML を最小限にとどめる効果も期待大) 配信するコンテンツがパーソナライズされたものであれば、 より高い効果が期待できます。 Next.js Conf 2021 感想

Slide 45

Slide 45 text

React Server Components の恩恵が受けられないケースもあると思います。 (現状は alpha 版なので、判断材料として不透明ですが) これは ISR が発表された時と同様に、 「いくつかある選択肢が更に増えた」と受け止めています。 Next.js Conf 2021 感想

Slide 46

Slide 46 text

Next.js x Granular Renderings

Slide 47

Slide 47 text

開発者が、以前も・これからも変わらず意識すべきことは 「ユーザー体験を中心に設計する」ということです。 Web Vitals を指針に改善し続けるという取り組みは、 開発者はもちろん、フレームワーク最大の関心ごとです。 Next.js x Granular Renderings

Slide 48

Slide 48 text

Next.js はこれまで、ページ単位で Rendering を選択するという 「きめ細かい (Granular)」アプローチを提供してきました。 これが Web Vitals にどの様に貢献するのか、 Next.js Conf 2021 で発表された新しい Rendering とあわせ、    ※ TTFB (Time To First Byte) サーバーの初期応答時間 / FCP (First Contentful Paint) 視覚コンテンツの初期表示時間 ※ LCP (Largest Contentful Paint) 最大視覚コンテンツの表示時間 / FID (First Input Delay) 初回入力までの遅延時間 LCP FID TTFB FCP を比較していきましょう。 Next.js x Granular Renderings

Slide 49

Slide 49 text

Origin Server API Server/DB 従来 SSR はデータ取得完了後にレスポンスを送信、 TTFB が遅くなる傾向に。 Request 【1】従来 SSR (Server-Side Rendering)

Slide 50

Slide 50 text

Origin Server API Server/DB TTFB の遅れにより、Web Vitals が全体的に後ろ倒しになる。 FID LCP FCP Request TTFB 【1】従来 SSR (Server-Side Rendering)

Slide 51

Slide 51 text

【1】従来 SSR (Server-Side Rendering) ■ リクエスト毎に算出するため、低パフォーマンス ■ 常に新しいデータを取得するため、データ整合性が確実 ■ パーソナライズ可能であり、個人情報なども表示できる ※ Cache-Control header が設定されていない前提であり、設定次第ではこの限りではありません

Slide 52

Slide 52 text

Origin Server API Server/DB Edge CDN ビルド時に静的生成せず、オンデマンドで静的生成。 Request No Cache 【2】ISR (fallback: “blocking”)

Slide 53

Slide 53 text

Origin Server API Server/DB 静的 HTML Cache がない場合、TTFB までは実質 SSR と同じ。 FID Request LCP FCP TTFB No Cache 【2】ISR (fallback: “blocking”) Edge CDN

Slide 54

Slide 54 text

Origin Server API Server/DB 生成した HTML は Edge CDN に Cache される。 FID Request Cache LCP FCP TTFB No Cache 【2】ISR (fallback: “blocking”) Edge CDN

Slide 55

Slide 55 text

■ ビルドタイムに静的生成せず、オンデマンドで静的生成が可能 ■ Cache がある場合、Edge CDN から HTML が返るため高速 ■ Cache がない場合、SSR と同様に Rendering を blocking ■ クローラーにコンテンツを確実にインデックスさせたい場合に利用 【2】ISR (fallback: “blocking”)

Slide 56

Slide 56 text

Origin Server API Server/DB Cache が無くても、コンテンツがない「Skeleton (= ...loading)」が返る。 FCP Request TTFB 【3】ISR (fallback: true) Edge CDN

Slide 57

Slide 57 text

Origin Server API Server/DB データ取得が完了するまで、ページは「...loading」状態に。 FCP Request TTFB 【3】ISR (fallback: true) Edge CDN

Slide 58

Slide 58 text

Origin Server API Server/DB データ取得が完了した後、ページが再描画される。 FID LCP FCP Request TTFB 【3】ISR (fallback: true) Edge CDN

Slide 59

Slide 59 text

Origin Server API Server/DB JSON と同時に静的 HTML が生成され、Edge CDN に Cache される。 FID LCP FCP Request TTFB Cache Cache 【3】ISR (fallback: true) Edge CDN

Slide 60

Slide 60 text

■ ビルドタイムに静的生成せず、オンデマンドで静的生成が可能 ■ Cache がある場合、Edge CDN から HTML が返るため高速 ■ Cache がない場合、Skeleton を返すため TTFB までが速い ■ クローラーに Skeleton がインデックスされるリスクがあった 【3】ISR (fallback: true)

Slide 61

Slide 61 text

■ ビルドタイムに静的生成せず、オンデマンドで静的生成が可能 ■ Cache がある場合、Edge CDN から HTML が返るため高速 ■ Cache がない場合、Skeleton を返すため TTFB までが速い ■ クローラーに Skeleton がインデックスされるリスクがあった Next.js 12 で追加された「Bot-Aware ISR Fallback」で心配なくなった。 【3】ISR (fallback: true) ※ Bot-Aware ISR Fallback の RFC:https://github.com/vercel/next.js/discussions/28180

Slide 62

Slide 62 text

Origin Server API Server/DB 静的 HTML Cache が Edge CDN から高速に配信。 FCP Request TTFB 【4】Static (Cache) + CSR Edge CDN

Slide 63

Slide 63 text

Origin Server API Server/DB パーソナライズが必要なコンテンツは、部分的に CSR を併用する。 FCP Request TTFB 【4】Static (Cache) + CSR Edge CDN

Slide 64

Slide 64 text

Origin Server API Server/DB Static Generation だけでなく、SSR でも用いられる構成。 FCP Request TTFB 【4】Static (Cache) + CSR LCP FID Edge CDN ※ LCP相当のコンテンツデータを fetch している前提

Slide 65

Slide 65 text

Origin Server API Server/DB JS ファイルがロードされた後に hydrate、fetch が開始。LCP までが遅い。 LCP FCP Request TTFB 【4】Static (Cache) + CSR Slow FID Edge CDN ※ LCP相当のコンテンツデータを fetch している前提

Slide 66

Slide 66 text

【4】Static (Cache) + CSR ■ Edge CDN の高速配信で TTFB を高速に ■ JS ファイルのロード完了後に fetch が開始するため、LCP までが遅い ■ 常に新しいデータを取得するため、データ整合性が担保できる ■ 部分的にパーソナライズ可能であり、個人情報なども表示できる ※ LCP相当のコンテンツデータを fetch している前提

Slide 67

Slide 67 text

ここから Next.js Conf 2021 で発表された 新しい Rendering 【5】Streaming with getServerSideProps (RFC) 【6】Streaming SSR @ Edge (alpha) 既存の getServerSideProps 拡張・React 17 でも使え【6】への移行を容易に

Slide 68

Slide 68 text

ここから Next.js Conf 2021 で発表された 新しい Rendering 【5】Streaming with getServerSideProps (RFC) 【6】Streaming SSR @ Edge (alpha) React Server Components を使い、React 18 以降が必要

Slide 69

Slide 69 text

Origin Server API Server/DB keynote とは別セッションで紹介された、getServerSideProps の拡張。 Request 【5】Streaming with getServerSideProps Edge CDN

Slide 70

Slide 70 text

Origin Server API Server/DB コンテンツデータ (LCP 相当) を取得する前に

Slide 71

Slide 71 text

Origin Server API Server/DB そのため、従来 SSR と比較し CSS / JS ロードが前倒しに。 FCP Request TTFB 【5】Streaming with getServerSideProps コンテンツデータ (LCP相当) CSS / JS Edge CDN

Slide 72

Slide 72 text

Origin Server API Server/DB データ取得が完了した段階で HTML の残りを flush し、ページを提供。 FID LCP FCP Request TTFB 【5】Streaming with getServerSideProps

Slide 73

Slide 73 text

Origin Server API Server/DB ここが Streaming で、このレスポンスは

Slide 74

Slide 74 text

【5】Streaming with getServerSideProps ■ Next.js 12 にはまだ搭載されておらず、RFC段階 ■ getServerSideProps が返す「props」に変更が加えられる ■ 従来 SSR のボトルネックであった、TTFB 遅延が改善 ■ データ取得開始のタイミングが CSR より前なので LCP までが速い ■ 次の【6】Streaming SSR@Edge への準備として有用 【詳細】Streaming in Next.js - Kara Erickson - (Next.js Conf 2021) https://youtu.be/Nl4OwNhh2QI?list=TLGG9L6VQs5dRz4xNTExMjAyMQ

Slide 75

Slide 75 text

API Server/DB Edge Computing でも Skeleton を返却する FCP Request TTFB Edge Computing 【6】Streaming SSR @ Edge (alpha)

Slide 76

Slide 76 text

API Server/DB データを取得し、HTML 生成が完了したものから Streaming FCP Request TTFB 【6】Streaming SSR @ Edge (alpha) Edge Computing

Slide 77

Slide 77 text

API Server/DB 断片的に送られてきた HTML を順次 Hydrate する FID LCP FCP Request TTFB 【6】Streaming SSR @ Edge (alpha) Edge Computing

Slide 78

Slide 78 text

API Server/DB React Server Components の初期表示にはこの Streaming SSR が使われる。 FID LCP FCP Request TTFB 【6】Streaming SSR @ Edge (alpha) Streaming Edge Computing

Slide 79

Slide 79 text

【6】Streaming SSR @ Edge (alpha) ■ まだ試験的な段階で、一部機能が試せるようになったばかり ■ Edge からの Streaming 配信により、全ての高速化が期待される ■ インフラを自由に選択できるのは、さらに将来の話になりそう 【詳細】Next.js at the Edge - Suzanne Aldrich + Lee Robinson - (Next.js Conf 2021) https://www.youtube.com/watch?v=WlP2TB2ORL4

Slide 80

Slide 80 text

Next.js x Granular Renderings まとめ

Slide 81

Slide 81 text

Next.js x Granular Renderings レンダリング手法は多岐にわたりますが、共通点があります。 それは、データ取得が必要なコンテンツを分割し 「早期に Skeleton を返却、TTFB を高速化する」という点です。 これは引き続き、重要なパートになります。

Slide 82

Slide 82 text

Next.js x Granular Renderings ■ コンテンツの性質に応じた Rendering が選択できているか ■ 静的事前生成エリア・データ取得エリアは、適切に分離できているか ■ Skeleton のデザインは考慮されているか パフォーマンスのために、デザイン面でも積極的に議論を。

Slide 83

Slide 83 text

Next.js x Granular Prefetch

Slide 84

Slide 84 text

Next.js x Granular Prefetch 提供されている Granular Renderings を選ぶだけでは、 3つの Core Web Vitals の指標のうち「CLS」の対策がとれません。 「視覚的な安定性」は、コンテンツの高さ変動に起因します。 これは Suspense の様な多段レンダリングはもちろん、 ...loading 表示(Skeleton 表示)についてまわる課題です。 ※ CLS(Cumulative Layout Shift)「累積レイアウト シフト数」視覚的な安定性を測定するための指標。

Slide 85

Slide 85 text

Next.js x Granular Prefetch ここで活きるのが「SWR」等のライブラリです。 Suspense と似たコンポーネント構成を取ることができ、 CSR における非同期データ取得を簡単にしてくれます。 そして Navigation に伴う ...loading 表示を削減し、 視覚的に安定した Navigation を提供できます。 ※ 以降「 Navigation 」は SPA における遷移を指します

Slide 86

Slide 86 text

CSR (Each Request) Edge / Origin API Server/DB あるページからの Navigation で、データを取得し CSR する例です。 Navigation Prev Page

Slide 87

Slide 87 text

CSR (Each Request) Edge / Origin API Server/DB Component マウントを hook にした fetch の場合、 Navigation Prev Page

Slide 88

Slide 88 text

Edge / Origin API Server/DB Navigation ごとに ...loading 表示が発生するため、体験がよくありません。 Navigation Prev Page CSR (Each Request)

Slide 89

Slide 89 text

SWR (No Cache) Edge / Origin API Server/DB In-Memory SWR を利用したデータ取得を見ていきます。Cache はまだ有りません。 Navigation Prev Page

Slide 90

Slide 90 text

SWR (No Cache) Edge / Origin API Server/DB In-Memory SWR で Component マウントと同時にデータを取得した場合、 Navigation Prev Page

Slide 91

Slide 91 text

SWR (No Cache) Edge / Origin API Server/DB In-Memory 取得したデータを Memory (ブラウザ) に Cache します。 Navigation Prev Page Cache

Slide 92

Slide 92 text

SWR (With Cache) Edge / Origin API Server/DB In-Memory この Cache がある場合、データが即座に返るので ...loading は表示されません。 Navigation Prev Page

Slide 93

Slide 93 text

SWR (With Cache) Edge / Origin API Server/DB In-Memory データは古くなっている可能性があるため、裏側で再取得を試みます。 Navigation Prev Page

Slide 94

Slide 94 text

SWR (With Cache) Edge / Origin API Server/DB In-Memory 再取得したデータに差分があった場合、再描画が走ります。 Re-Render Navigation Prev Page

Slide 95

Slide 95 text

SWR (With Cache) Edge / Origin API Server/DB In-Memory 取得したデータは新しい Cache として、次回活用されます。 Re-Render Navigation Prev Page Cache

Slide 96

Slide 96 text

Edge / Origin API Server/DB In-Memory Cache を保持した状態で Navigation すると、視覚的に安定します。 Navigation Prev Page SWR (Programmatically Prefetch)

Slide 97

Slide 97 text

SWR (Programmatically Prefetch) Edge / Origin API Server/DB In-Memory そこで、Navigation 前にデータを取得してしまうのが Prefetch です。 Navigation Prev Page Cache

Slide 98

Slide 98 text

SWR (Programmatically Prefetch) Edge / Origin API Server/DB In-Memory mutate を先行して実行すると、あらかじめ取得したデータを Cache できます。 Navigation Prev Page Cache ※ Programmatically Prefetch:https://swr.vercel.app/docs/prefetching#programmatically-prefetch

Slide 99

Slide 99 text

next/link (Prefetch) Navigation Prev Page Cache API Server/DB next/link による Prefetch は、SWR による Prefetch と同等の効果があります。 In-Memory Edge / Origin ※ Route prefetching in Next.js: https://web.dev/route-prefetching-in-nextjs/

Slide 100

Slide 100 text

next/link (Prefetch) Prev Page API Server/DB next/link はリンク先ページに getStaticProps が定義されている場合、 In-Memory Edge / Origin

Slide 101

Slide 101 text

Prev Page Cache API Server/DB マウスオーバー等をトリガーに、遷移先の getStaticProps を実行します。 next/link (Prefetch) In-Memory Edge / Origin

Slide 102

Slide 102 text

Prefetch は高速な Navigation を実現し、視覚的安定性に貢献します。 Navigation Prev Page Cache API Server/DB next/link (Prefetch) In-Memory Edge / Origin

Slide 103

Slide 103 text

SWR (Programmatically Prefetch) Edge / Origin API Server/DB In-Memory SWR の Cache Prefetch は、パーソナライズドデータも扱えます。 Navigation Prev Page Cache

Slide 104

Slide 104 text

Next.js x Granular Prefetch いずれの Prefetch も視覚的安定性に有用です。 しかし「表示されるであろう予測」にもとづくデータ取得は、 無駄になってしまう事もあります。 next/link は大味な Prefetch がデフォルトなので、注意が必要です。 【参考】Link と ISR が引き起こす Next.js の過負荷 https://zenn.dev/takepepe/articles/nextjs-isr-prefetch

Slide 105

Slide 105 text

Next.js x Granular Prefetch SWR では Prefetch を行う Component は提供されていません。 next/link と同じように振る舞う Component を用意すれば、 遷移後の ...loading 表示を限りなく抑えられるでしょう。 過度の Prefetch とならないよう、バランスを取ることが肝心です。

Slide 106

Slide 106 text

Next.js x Granular Prefetch 【Next.js には不向きですが余談】 まさにこの Client Side の Cache Prefetch 機構を実現したのが 「React Location」です。 React Query 作者の Tanner 氏が router ライブラリとして先日発表。 routing と prefetching のインテグレーションを提供しています。 【参考】React Location https://react-location.tanstack.com/

Slide 107

Slide 107 text

Next.js x Granular Chunk

Slide 108

Slide 108 text

SPA Chunk Problems Next.js の様なフレームワークがなかったころ、 SPA は単一の chunk に結合されてしまうなど、 適切に chunk 分割されているとは限りませんでした。 chunk 分割はやや敷居が高く、 誰もが無意識にできていた事ではありませんでした。

Slide 109

Slide 109 text

SPA Chunk Problems chunk ファイルが適切に分割されていないと、 「ファイルのロード・解析・実行」というApp 起動に、 多くの時間を有することを意味します。 どういうことなのか、簡単な概念図でみていきます。

Slide 110

Slide 110 text

SPA Chunk Problems 最初のページを、80KB でスタートしたとします。 80 KB Page Bytes Page Sources Common Sources Single Chunk

Slide 111

Slide 111 text

SPA Chunk Problems 2ページ追加したことで、Chunk が 50 KB 増加しました。 Single Chunk 130 KB + 50 KB Page Bytes Page Sources Common Sources 130 KB 130 KB

Slide 112

Slide 112 text

SPA Chunk Problems 最初のページは変更が無いにもかかわらず、50 KB 増加しています。 Single Chunk 130 KB + 50 KB Page Bytes Page Sources Common Sources 130 KB 130 KB

Slide 113

Slide 113 text

SPA Chunk Problems ページが増えていくごとに、全ページの立ち上がり速度が低下します。 Single Chunk 180 KB + 100 KB Page Bytes Common Sources Page Sources 180 KB + 50 KB 180 KB 180 KB + 50 KB 180 KB

Slide 114

Slide 114 text

Chunk Per Page 従来 SPA においては、この課題が顕著でした。 Next.js では「ページ単位」で chunk が分割されるため、 自然と必要最小限のコードのみが、 立ち上げ時にロードされる様になります。

Slide 115

Slide 115 text

Chunk Per Page 最初の1ページは同様に、80KB でスタート。 Page Chunk 80 KB Page Bytes Page Sources Common Sources

Slide 116

Slide 116 text

Chunk Per Page 最初のページに関係ない Source は、該当ページの Chunk には含まれません。 Page Chunk 80 KB Page Bytes Page Sources Common Sources 50 KB 60 KB

Slide 117

Slide 117 text

Chunk Per Page ページが増えても、影響のないページの立ち上がり速度は低下しません。 Page Chunk 80 KB Page Bytes Page Sources Common Sources 50 KB 60 KB 60 KB 50 KB

Slide 118

Slide 118 text

Chunk Per Page 不要な初期スクリプトの読み込みは、TBT・TTI に影響します。 ページ単位の chunk 分割は、Next.js で開発する十分な動機になります。 chunk 肥大化を意識することなく、 必要な機能を追加し続けることができます。

Slide 119

Slide 119 text

Chunk Per Page ページ単位の chunk 分割のほか、 Google Chrome チーム (現 Aurora チーム) の協力のもと、 部分的に共通している実装を効率的に chunk 分割する 「granular chunking」が導入されたことも話題になりました。 【詳細】Improved Next.js and Gatsby page load performance with granular chunking https://web.dev/granular-chunking-nextjs/

Slide 120

Slide 120 text

Common Sources Problems しかし、フレームワークの用意したソリューションにも限界はあります。 共通ソースファイルは設計次第で「太り」やすくなります。 お手元の _app chunk サイズがどの様に肥大化していったか、 コミットを遡って調べてみてください。 本当に App 起動時に必要なコードに絞られているでしょうか?

Slide 121

Slide 121 text

特定のページに 20 KB ぶんの実装を追加をする必要が出たとします。 Page Chunk 80 KB Page Bytes Page Sources Common Sources 50 KB 60 KB 60 KB 50 KB Common Sources Problems

Slide 122

Slide 122 text

本来は必要なページでのみ、20 KB 増加としたいです。 Page Chunk 80 KB Page Bytes Page Sources Common Sources 50 KB 80 KB + 20 KB 60 KB 50 KB + 20 KB Common Sources Problems

Slide 123

Slide 123 text

しかし設計都合で _app に実装を追加するしかなく、共通 Sources が肥大化。 Page Chunk 100 KB + 20 KB Page Bytes Page Sources Common Sources 70 KB + 20 KB 80 KB + 20 KB 80 KB + 20 KB 70 KB + 20 KB + 20 KB _app.tsx Common Sources Problems

Slide 124

Slide 124 text

全てのページで 20 KB の増加が余儀なくされました。 Page Chunk 100 KB + 20 KB Page Bytes Page Sources Common Sources 70 KB + 20 KB 80 KB + 20 KB 80 KB + 20 KB 70 KB + 20 KB + 20 KB _app.tsx Common Sources Problems

Slide 125

Slide 125 text

状態管理の実装であったり、Global UI の実装次第では、 この肥大に伴う「起動初速の低下」は不可避かもしれません。 有名どころで言うと、Redux の Reducer は不可避ですし、 React.Context Provider を _app に置いた場合も、この状態となります。 granular chunking をもってしても、この問題が混入します。 Common Sources Problems

Slide 126

Slide 126 text

また、型安全のために自動生成した fetch client でも 不要な実装を含めてしまう懸念があります。 aspida は `outputEachDir: true` を指定しなければこの状態になりますし、 graphql-codegen でも以下参考記事のように分割指定をするべきです。 OpenAPI から型定義のみ出力する、というのも良いでしょう。 Common Sources Problems 【参考】next.jsでのファイルチャンク最適化の一例 https://blog.hiroppy.me/entry/2021/08/12/092839

Slide 127

Slide 127 text

以下の観点で、設計初期から共通 Sources 肥大化に気をつけましょう。 ■ chunk 分割しやすい状態管理ライブラリを使っているか ■ 自動生成される fetch client 等は、ユースケース単位で分割できているか ■ Context Provider の適用範囲は、ページ単位に閉じることはできないか ■ _app に実装を追加する場合、将来どの様に肥大化するか想定しておく Common Sources Problems

Slide 128

Slide 128 text

Conclusion

Slide 129

Slide 129 text

Conclusion 近年 Aurora チームの密接な連携により、 Next.js を使用したサイトの 91% 以上が 優れた Core Web Vitals を獲得したそうです。 誰もが最適化の恩恵を受けている証です。 ※ 引用:https://twitter.com/hdjirdeh/status/1457679313965240325

Slide 130

Slide 130 text

Conclusion 【詳細】Performance as a default with Next.js https://web.dev/performance-as-a-default-with-nextjs/ これまでの取り組みの内容は web.dev に寄稿があります。 Next.js に搭載された機能とあわせて、 パフォーマンスにどう向き合うべきか 調べてみましょう。 ※ 引用:https://twitter.com/hdjirdeh/status/1457679327630266369

Slide 131

Slide 131 text

Conclusion 今日紹介したように、より良いパフォーマンスを追求するためには、 工夫を凝らしたり・注意しなければいけない事もあります。 新しい機能が出たからといって、その機能が 全てのサイトにとって最適解ではないこともあります。 計測し、自分たちにとって最適なものを選んでいきましょう。

Slide 132

Slide 132 text

より速い Web を目指しましょう!! ー ご清聴ありがとうございました ー