Slide 1

Slide 1 text

フロントアーキテクチャ改善 NIGHT App Router への移行は 「改善」となり得るのか?

Slide 2

Slide 2 text

自己紹介 ■ Takepepe(吉井 健文) ■ フロントエンドエンジニア ■ 社内横断開発組織に所属 ■ フロントエンド開発の横断サポート

Slide 3

Slide 3 text

実践Next.js – App Router で進化する Web アプリ開発 ■ 2024.3/16 技術評論社より刊行 ■ Next.js App Router を題材にした書籍 ■ 一通りの機能を備えたサンプル App を対象に解説 ■ 公式ドキュメントの分かりづらい箇所を重点的に

Slide 4

Slide 4 text

■ 【1】App Router 登場の背景 ■ 【2】パフォーマンスへの影響 ■ 【3】アーキテクチャへの影響 Agenda

Slide 5

Slide 5 text

【1】App Router 登場の背景

Slide 6

Slide 6 text

これらの機能は Next.js 固有のものではなく、 React 共通のもの ■ React の新しい機能が使用できる ・ RSC(React Server Components)がデフォルトで使用される ・ Server Component / Client Component の境界がある ・ Server Action が使用できる 従来 Pages Router との差分 【1】App Router 登場の背景

Slide 7

Slide 7 text

パフォーマンス向上のための機能 ■ React の新しい機能が使用できる ・ RSC(React Server Components)がデフォルトで使用される ・ Server Component / Client Component の境界がある ・ Server Action が使用できる 従来 Pages Router との差分 【1】App Router 登場の背景

Slide 8

Slide 8 text

■ RSC に適したキャッシュ機構をもつ ・ RSCペイロードと呼ばれるレンダリング結果をキャッシュ ・ コンポーネント単位で、キャッシュの存続期間をコントロール ・ 動的/静的を区分し、キャッシュを作成 ・ キャッシュにより、更なるパフォーマンス向上が見込まれる App Router の優位性 【1】App Router 登場の背景

Slide 9

Slide 9 text

【2】パフォーマンスへの影響

Slide 10

Slide 10 text

■ SPA でも十分速いのですが… ・ ページ総数が増加するとどうですか? ・ 各ページのコンテンツが肥大化するとどうですか? パフォーマンス向上と言われても… 【2】パフォーマンスへの影響 将来も、現状と同じパフォーマンスを維持できるでしょうか?

Slide 11

Slide 11 text

ページ単位で CSR を行うも、全ての実装が共通チャンクに含まれる (※ React.lazy による Dynamic import で分割し、最適化する方法もあります) 従来 SPA のパフォーマンス課題 【2】パフォーマンスへの影響 Request Response Web Server per page chunk per page chunk per page fetch HTML Commons chunk fetch Page render (CSR)

Slide 12

Slide 12 text

いずれかのページ実装増加が、全ページのパフォーマンスに影響する (※ React.lazy による Dynamic import で分割し、最適化する方法もあります) 従来 SPA のパフォーマンス課題 【2】パフォーマンスへの影響 Request Response Web Server per page chunk per page chunk per page fetch HTML Commons chunk fetch Page render (CSR)

Slide 13

Slide 13 text

ページ単位で チャンクが分割されている Pages Router のページ毎のチャンク 【2】パフォーマンスへの影響 fetch render (CSR) Request Response Next.js HTML DOM Request Response Next.js HTML DOM Request Response Next.js HTML DOM page chunk page chunk page chunk

Slide 14

Slide 14 text

いずれかのページチャンク増加は、該当ページに「のみ」パフォーマンス影響がある Pages Router のページ毎のチャンク 【2】パフォーマンスへの影響 fetch render (CSR) Request Response Next.js HTML DOM Request Response Next.js HTML DOM Request Response Next.js HTML DOM page chunk page chunk page chunk

Slide 15

Slide 15 text

■ 利点 ・ ページ固有の実装は、ページ単位のチャンクに分割される ・ ページ固有の実装は、他ページに影響を与えない ・ チャンクの共通化は、自動で行われる ・ ページ毎に、レンダリング手法(SSG / ISR / SSR)を選べる Pages Router のメリット ページが増えても、他ページのパフォーマンスが劣化しにくい構造 【2】パフォーマンスへの影響

Slide 16

Slide 16 text

ただし、1ページ内のコンテンツ増加に対して、チャンク増加は不可避だった Pages Router のページ毎のチャンク 【2】パフォーマンスへの影響 fetch render (CSR) Request Response Next.js HTML DOM Request Response Next.js HTML DOM Request Response Next.js HTML DOM page chunk page chunk page chunk

Slide 17

Slide 17 text

ただし、1ページ内のコンテンツ増加に対して、チャンク増加は不可避だった Pages Router のページ毎のチャンク 【2】パフォーマンスへの影響 fetch render (CSR) Request Response Next.js HTML DOM Request Response Next.js HTML DOM Request Response Next.js HTML DOM page chunk page chunk page chunk

Slide 18

Slide 18 text

App Router(RSC) は、このチャンク増加をなるべく避ける仕組みを提供します Pages Router のページ毎のチャンク 【2】パフォーマンスへの影響 fetch render (CSR) Request Response Next.js HTML DOM Request Response Next.js HTML DOM Request Response Next.js HTML DOM page chunk page chunk page chunk

Slide 19

Slide 19 text

ビルド時、ページのコンテンツは空 Pages Router の SSR 【2】パフォーマンスへの影響 ready Server

Slide 20

Slide 20 text

リクエスト時、ページのデータを取得 Pages Router の SSR fetch Request Server 【2】パフォーマンスへの影響

Slide 21

Slide 21 text

リクエスト時、ページのデータを取得 Pages Router の SSR fetch Request Server { "tags": [...], "articles": [...], "recommendations": [...], "categories": [...], } getPageData JSON 【2】パフォーマンスへの影響

Slide 22

Slide 22 text

取得したデータを使用し、ページを render Pages Router の SSR fetch render Request Server 【2】パフォーマンスへの影響

Slide 23

Slide 23 text

レスポンス後、ページに必要なチャンクを読み込み、ページ全体を hydration Pages Router の SSR fetch render hydration Response Request Browser Server TTFB 【2】パフォーマンスへの影響

Slide 24

Slide 24 text

レスポンス後、ページに必要なチャンクを読み込み、ページ全体を hydration Pages Router の SSR fetch render hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS TTFB

Slide 25

Slide 25 text

ページ全体がインタラクティブに Pages Router の SSR fetch FID render hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS TTFB

Slide 26

Slide 26 text

■ 欠点 ・ ページに必要なデータが多くなるほど、 TTFBが遅くなる ・ ページのコンテンツが多くなるほど、ページのチャンクが肥大化する ・ ページのコンテンツが多くなるほど、 hydration に時間がかかる ・ ページのチャンク肥大化に伴い、 FID が遅延 Pages Router の SSR ページの肥大化にともない、パフォーマンスが劣化する構造 【2】パフォーマンスへの影響

Slide 27

Slide 27 text

■ 欠点 ・ ページに必要なデータが多くなるほど、 TTFBが遅くなる ・ ページのコンテンツが多くなるほど、ページのチャンクが肥大化する ・ ページのコンテンツが多くなるほど、 hydration に時間がかかる ・ ページのチャンク肥大化に伴い、 FID が遅延 Pages Router の SSR Next.js に限らず RSC ではない SSR の場合、共通の課題 【2】パフォーマンスへの影響

Slide 28

Slide 28 text

ビルド時に予め「静的データ」を取得 App Router の Streaming SSR Server build 【2】パフォーマンスへの影響

Slide 29

Slide 29 text

ビルド時に予め「静的データ」を取得 App Router の Streaming SSR build Server { "tags": [...], "articles": [...], "categories": [...], } getStaticData JSON 【2】パフォーマンスへの影響

Slide 30

Slide 30 text

「静的データ」でレンダリングできる部分は、予めレンダリングしておく App Router の Streaming SSR ready Server 【2】パフォーマンスへの影響

Slide 31

Slide 31 text

リクエスト時に「動的データ」を取得 App Router の Streaming SSR fetch Server Request 【2】パフォーマンスへの影響

Slide 32

Slide 32 text

リクエスト時に「動的データ」を取得 App Router の Streaming SSR fetch Request Server 【2】パフォーマンスへの影響 { "recommendations": [...], } getDynamicData JSON

Slide 33

Slide 33 text

動的データ取得中でも、 Streaming でレスポンスが返せる App Router の Streaming SSR fetch Response Request Server Browser 【2】パフォーマンスへの影響 TTFB { "recommendations": [...], } getDynamicData JSON

Slide 34

Slide 34 text

送られたコンポーネントから個別に hydration が行われる(コンポーネント単位のチャンク) App Router の Streaming SSR fetch hydration Response Request Browser Server 【2】パフォーマンスへの影響 TTFB

Slide 35

Slide 35 text

送られたコンポーネントから個別に hydration が行われる(コンポーネント単位のチャンク) App Router の Streaming SSR fetch hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS JS TTFB

Slide 36

Slide 36 text

「動的データ」の取得が完了し、部分的なレンダリング結果が返される App Router の Streaming SSR fetch hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS JS TTFB

Slide 37

Slide 37 text

後から送られてきたコンポーネントの hydration も始まる App Router の Streaming SSR fetch hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS JS JS TTFB FID

Slide 38

Slide 38 text

ページ全体がインタラクティブに App Router の Streaming SSR fetch hydration Response Request Browser Server 【2】パフォーマンスへの影響 JS JS JS FID TTFB

Slide 39

Slide 39 text

■ 利点 ・ ページに必要なデータが多くなっても、 TTFBが遅くならない ・ ページのコンテンツが多くなっても、ページのチャンクが肥大化しにくい ・ ページのコンテンツが多くなっても、 hydration は適宜行われる ・ ブラウザに必要な JS が最小限であり、チャンクはコンポーネント毎に分割 App Router の Streaming SSR ページが肥大化しても、パフォーマンスが劣化しにくい構造 【2】パフォーマンスへの影響

Slide 40

Slide 40 text

■ 利点 ・ ページに必要なデータが多くなっても、 TTFBが遅くならない ・ ページのコンテンツが多くなっても、ページのチャンクが肥大化しにくい ・ ページのコンテンツが多くなっても、 hydration は適宜行われる ・ ブラウザに必要な JS が最小限であり、チャンクはコンポーネント毎に分割 App Router の Streaming SSR さらにナビゲーション時、必要なコンポーネントのみ SSR されるため、データ取得効率が良好 【2】パフォーマンスへの影響

Slide 41

Slide 41 text

■ RSC はパフォーマンス改善となりうるのか? ・ RSC では、チャンクがコンポーネント単位で細分化される ・ RSC に最適化された App Router キャッシュは、パフォーマンス向上に寄与 ・ 中長期的にみて「劣化しにくい」構造が得られる パフォーマンスへの影響まとめ 画面構成要素が少ない場合、差が生まれにくいのも事実 【2】パフォーマンスへの影響

Slide 42

Slide 42 text

【3】アーキテクチャへの影響

Slide 43

Slide 43 text

■ 【構成例1】SPA + BFFサーバーパターン(非 Next.js) ■ 【構成例2】Next.js の Routing のみ活用パターン ■ 【構成例3】Next.js の BFF フル活用パターン 筆者が直面したことのある構成 アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響

Slide 44

Slide 44 text

アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響 BFF Server Web API Request Web Server Data Source 【構成例1】SPA + BFFサーバーパターン(非 Next.js) DB SPA

Slide 45

Slide 45 text

アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響 BFF Web API Request SSG + SPA Data Source 【構成例2】Next.js の Routing のみ活用パターン DB Server Next.js

Slide 46

Slide 46 text

アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響 Web API Request SSG / ISR SSR + SPA Data Source 【構成例3】Next.js の BFF フル活用パターン DB Server Next.js

Slide 47

Slide 47 text

■ 【構成例1】SPA + BFFサーバーパターン(非 Next.js) ・ Node.js サーバーを運用したくない現場(監視面、チューニング面など) ・ Vite(create-react-app)や、最近だと Remix SPA モード を採用 ・ Next.js Pages Router の Static Export で乗り切るパターンも存在 ・ FE/BE をキッチリ分割したい現場向け 運用面 >>> パフォーマンス アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響

Slide 48

Slide 48 text

■ 【構成例2】Next.js の Routing のみ活用パターン ・ Next.js の Static Export だと Dynamic Route が処理しづらい ・ ファイルシステムベース Routing が便利なので使用している ・ Node.js 製の BFF サーバーは、BEエンジニアが実装 認証認可実装は、構成例 1と同じ アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響

Slide 49

Slide 49 text

■ 【構成例3】Next.js の BFF フル活用パターン ・ 認証認可を Next.js の BFF で行う ・ 外部 WEB API サーバーは、BE エンジニアが開発 ・ 外部 WEB API サーバーは、マイクロサービス化されていることも ・ BFF から ORM(DBサーバー)を直接使うことも Node.js(Next.js)サーバーのチューニングや運用の知見が求められる アーキテクチャ上の Next.js 立ち位置 【3】アーキテクチャへの影響

Slide 50

Slide 50 text

■ 【構成例1】SPA + BFFサーバーパターン(非 Next.js) ■ 【構成例2】Next.js の Routing のみ活用パターン ■ 【構成例3】Next.js の BFF フル活用パターン App Router への移行は 「改善」となり得るのか? 【3】アーキテクチャへの影響

Slide 51

Slide 51 text

■ 【構成例1】SPA + BFFサーバーパターン(非 Next.js)❌ ■ 【構成例2】Next.js の Routing のみ活用パターン ■ 【構成例3】Next.js の BFF フル活用パターン Next.js サーバーを運用しない場合、メリットは今の所無い App Router への移行は 「改善」となり得るのか? 【3】アーキテクチャへの影響

Slide 52

Slide 52 text

■ 【構成例1】SPA + BFFサーバーパターン(非 Next.js)❌ ■ 【構成例2】Next.js の Routing のみ活用パターン ✅ ■ 【構成例3】Next.js の BFF フル活用パターン ✅ App Router への移行は 「改善」となり得るのか? 【3】アーキテクチャへの影響 Next.js サーバーを運用している場合、パフォーマンス面でメリット

Slide 53

Slide 53 text

■ App Router では React の新機能 Server Action が使える ・ Form を通じ、サーバーの更新処理がダイレクトに行える ・ 中継点として設けていた WEB API(API Routes、Route Handlers)が不要に 他 React 製フレームワークでも Server Action は今後採用例が出る見込み 【3】アーキテクチャへの影響 App Router への移行は 「改善」となり得るのか?

Slide 54

Slide 54 text

■ WEB API は RESTful API の方が都合が良い ・ キャッシュの再利用がしやすく、 revalidate が単純 ■ 別立ての BFF サーバーは恐らく不要に ・ Server Component / Server Action で ORM を使用する機会が増加 ■ Page 層で req / res オブジェクトが使用不能に ・ req / res を使用している従来のコードは再検討が必要 App Router への移行は 「改善」となり得るのか? 【3】アーキテクチャへの影響 App Router を採用する場合、従来アーキテクチャへの影響は大きい

Slide 55

Slide 55 text

■ まとめ ・ App Router への移行は、フロント外のアーキテクチャにも影響を及ぼす ・ App Router への移行は、既存構成によって難易度が異なる ・ アーキテクチャ改善というより、改変になる App Router への移行は 「改善」となり得るのか? 【3】アーキテクチャへの影響 各位、メリット/デメリットを比較して

Slide 56

Slide 56 text

ご清聴ありがとうございました