Upgrade to Pro — share decks privately, control downloads, hide ads and more …

より速い WEB を目指す Next.js / nextjs-make-the-web-faster

Takepepe
November 24, 2021

より速い WEB を目指す Next.js / nextjs-make-the-web-faster

【Next.js Update!】v12リリースを踏まえ、Next.jsの採用を考える

本発表は以下URLでアーカイブ視聴が可能です。https://youtu.be/KaS3bgz_CA4

イベントページ:https://forkwell.connpass.com/event/228457/

Takepepe

November 24, 2021
Tweet

More Decks by Takepepe

Other Decks in Technology

Transcript

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

    View full-size slide

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

    View full-size slide

  3. 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

    View full-size slide

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

    View full-size slide

  5. 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までは、上の動画内容をおさらいします

    View full-size slide

  6. Static x Dynamic

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  25. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. React Server
    Components x Edge

    View full-size slide

  31. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  37. Next.js Conf 2021 感想

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  40. ひとつは、誰もがすぐに開発を始められることです。
    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

    View full-size slide

  41. 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.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  46. Next.js x Granular
    Renderings

    View full-size slide

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

    View full-size slide

  48. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  61. ■ ビルドタイムに静的生成せず、オンデマンドで静的生成が可能
    ■ 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  74. 【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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  79. 【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

    View full-size slide

  80. Next.js x Granular Renderings
    まとめ

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  83. Next.js x Granular
    Prefetch

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  98. 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

    View full-size slide

  99. 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/

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  106. 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/

    View full-size slide

  107. Next.js x Granular
    Chunk

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  113. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  119. 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/

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  122. 本来は必要なページでのみ、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

    View full-size slide

  123. しかし設計都合で _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

    View full-size slide

  124. 全てのページで 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  129. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide