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

Next.jsから見る Webフロントエンドの歴史

Next.jsから見る Webフロントエンドの歴史

2023/10/26 RUNTEQ LT会

Yusuke Inai

October 26, 2023
Tweet

More Decks by Yusuke Inai

Other Decks in Programming

Transcript

  1. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React Server Components と App Router 1. 2. 3. 4. 5.
  2. 🙅‍♂️ 話さないこと React / Next.js の各機能についての説明 Hooks, Rendering, Managing State,

    Suspense Routing, Cache, Server Actions 3rd Party ライブラリやツール等の使い方 UI ライブラリ, テスト, Storybook, etc. ハンズオン
  3. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React Server Components と App Router 1. 2. 3. 4. 5.
  4. HTML M C V <html> <body> <div><%= @user.name %></div> </body>

    </html> HTML = Template (data) Web MVCフレームワーク APサーバ ブラウザ DB data テンプレート
  5. Web MVCフレームワーク サーバーサイドでは MVC を利用 Ruby on Rails, Laravel, Spring,

    etc. View には「テンプレート」を利用 例: ERB, Blade, JSP, etc. HTML = Template (data) リクエスト毎にページ全体をレンダリングして返す
  6. ブラウザ間で言語仕様が 異なり、実装者は大変 JavaScript不遇期 Web でも良質な UX が求 められ始める! インタラクティ ブなコンテンツ

    の普及 JavaScriptの歴史 JavaScript台頭 Netscape Navigator と IE で 実装された ECMAScript / Flash ブラウザ間の仕様を統一する ため、ECMAScriptが策定。 Flashも登場 Ajax / HTML5 Google Map により Ajax が 注目される。またHTML5 に より API が充実 iPhone / Android ネイティブアプリの普及
  7. JavaScriptの台頭 1995年 Netscape Navigator 2.0 に実装 翌年にはInternet Explorer 3.0 にも搭載され、急速に

    普及 ECMAScriptの誕生 ブラウザ間での言語仕様を統一 開発者にとって使い勝手の良いものへ
  8. HTML M C V APサーバ ブラウザ DB MPA(クラシックSSR + jQuery)

    インタラクション Webサーバ <script src=”...” /> DOM イベントハンドラ 登録 イベント DOMを操作 JS
  9. MPA(クラシックSSR + jQuery) クラシック SSR が生成した HTML と連携する JS を

    あとづけ コンテンツ、スタイル、ロジックを分離するのがベストプラク ティスだった 2006 年 jQuery 「write less, do more」 ブラウザ間の差異を吸収
  10. HTML M C V DOM JS テンプレート フロントエンド側で 開発するリソース サーバーサイド側で

    開発するリソース 開発リソースではない MPA(クラシックSSR + jQuery)の課題: ワークフロー APサーバ ブラウザ DB Webサーバ 依 存 齟齬 スケジュール 二重開発
  11. MPA(クラシックSSR + jQuery)の課題: ワークフロー 「HTML」はリソースではない リソースは「テンプレート」 JS の処理対象となるのは AP サーバの実行結果

    JS 側が必要とする HTML の修正は誰がするのか? テンプレートの修正。サーバーサイド側? 開発サイクルが異なる 二重開発 サーバーサイドのテンプレートとフロントの JS が機能的に重複
  12. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React Server Components と App Router 1. 2. 3. 4. 5.
  13. HTML DOM JS SPA (Single Page Application) サーバ ブラウザ フォームをサブミット

    イベント DOM更新 イベント DOM更新 JSON JSON リンクをクリック ブクマ等から ロードされる HTML ページは1つ (Documentオブジェクトは不変)
  14. SPA (Single Page Application) Single Page Application ナビゲーションの画面遷移もブラウザ上の JS でレンダリング

    単一の HTML ページ(あるいは Document)だけで構成 ナビゲーションの単位も「ページ」と呼ばれる 例)トップページ、一覧ページ、商品ページ、etc.
  15. 静的 HTML DOM JS SPA の起動シーケンス Web サーバ ブラウザ レンダリング

    インタラクション JSON API サーバ JSON DB (CSR) イベント レンダリング (CSR) コンテンツとしては空 (SSR 不要)
  16. SPA の起動シーケンス 基本的には CSR (Client-Side Rendering)のみ クライアントサイド(ブラウザ)だけでコンテンツをレンダリ ング サーバサイドでは HTML

    ページを動的にレンダリングしない ここでの「レンダリング」とは、単純な HTML 生成処理 広義の「レンダリング」 react.dev でいうところの “Rendering” とは違う
  17. フロントエンドと状態 クライアントサイドで状態を扱うことが増える ステートレス→ステートフル 画面の表示 → ユーザのアクション → 状態の変化 → 画面の表

    示... 状態の例(保持されていて変化・変更するもの) TODOリストのデータ(Model State) モーダルの開閉状態(UI State) どのページを開いているか?(Location State) 誰がログインしているか?(Auth State) 状態は「スコープ」と「ライフタイム」を持つ
  18. MV* フレームワークと状態 クラシックSSR + jQuery DOM 状態 イベントハンドラ 参照 更新

    イベント MV* フレームワーク DOM Controller イベント View 更新 Model 状態 更新要求 変更通知
  19. MV* フレームワーク MV* フレームワークの登場 例: Backbone.js, Angular JS, etc. 10年代半ば以降は

    MV* フレームワークではない React と VueJS が主流になった MPA(クラシックSSR + jQuery)の問題を解決 フロントエンドのアプリケーションに構造が付与 https://speakerdeck.com/nrslib/how-to-make-front-end DOM のグローバル定数化・イベントハンドラの散らばり↓ サーバサイドのテンプレートが不要に サーバサイドと疎結合に。HTML / CSS / JS がフロント側で完結
  20. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React ServerComponents と App Router 1. 2. 3. 4. 5.
  21. React The library for web and native user interfaces Web

    とネイティブユーザインターフェースのためのライブラリ 開発元は Meta (旧 Facebook) フロントエンド界の(現)覇者 語りたいことは色々あるが、結局は以下の 2 つに集約 される コンポーネント指向 宣言的 UI ⇔ UI = f (state)
  22. コンポーネント指向 MV* DOM Controller イベント View コンテンツ Model 状態 更新要求

    変更通知 React DOM ロジック ロジック 状態 コンテンツ Component ロジック 状態 コンテンツ Component ロジック 状態 コンテンツ Component 更新 更新 子コンポーネント (複数可)
  23. コンポーネント指向 React の構成要素はコンポーネント Model, Controllerなどは不要。 View と Modelの同期も気にする必要ない コンポーネントが持つもの ロジック、イベントハンドラ

    状態 コンテンツ(JSX) コンポーネントは親子関係を持つ 各部分を担当するコンポーネントにわける メンテナンス性や再利用性↑
  24. <form>  <input type=”checkbox”>  ... </form> 宣言的 UI ⇔ UI =

    f (state) DOM(UI) 状態 f (レンダリング) <form>  <input type=”checkbox” checked>  ... </form> 状態 f (レンダリング) ユーザー操作による変化 ・・・ DOM(UI)
  25. 宣言的 UI ⇔ UI = f (state) React のメンタルモデル 「変化の過程」ではなく「結果」を記述(=宣言的)

    毎回新規にレンダリングするのに近い。面倒な DOM 更新は React 側が担う 「状態」と「UI」を明確に分離 →「状態」が SSoT UI = f (state)。UI は現在の状態の映写機 クラシック SSR と類似 リクエストごとにテンプレート実行 → HTML 生成 HTML = Template (data) 面倒な DOM 更新については、jQueryのお仕事 これを自力でやろうとするからつらみ...
  26. ③状態が更新 仮想 DOM A B C <div> <span> <span> “Foo”

    “Bar” <div> <span> <span> “Foo” “Bar” コンポーネント 仮想DOM 実DOM A B C <div> <span> <span> “Baz” “Bar” <div> <span> <span> “Baz” “Bar” 最初の レンダリング 再レンダリング ①実行 ②反映 ④実行 ⑥差分反映 ⑤比較
  27. ③状態が更新 仮想 DOM A B C <div> <span> <span> “Foo”

    “Bar” <div> <span> <span> “Foo” “Bar” コンポーネント 仮想DOM 実DOM A B C <div> <span> <span> “Baz” “Bar” <div> <span> <span> “Baz” “Bar” 最初の レンダリング 再レンダリング ①実行 ②反映 ④実行 ⑥差分反映 ⑤比較 レンダー コミット 広義のレンダリング
  28. 仮想 DOM React のメンタルモデル 「変化の過程」ではなく「結果」を記述(=宣言的) 毎回新規にレンダリングするのに近い。面倒な DOM 更新は React 側が担う

    毎回全更新だと遅い そこで登場するのが「仮想 DOM」 DOM の代わりに軽量なJSオブジェクトで仮想 DOM 構築 VDOM = f (state) 差分更新(Reconciliation) 前回レンダリング時と新しい仮想 DOM を比較 → 実DOM へ反映
  29. ※仮想 DOMの補足 HTML = <div></div> DOM API = document.createElement("div") 仮想

    DOM 構造体 = React.createElement("div") 仮想 DOM アルゴリズムの実行 =ReactDOM.render(<App />, el) 前後の 2 つの木構造の比較することで、その差分を埋める操作を 自動的に導出できるはず、というのがスタート地点
  30. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React ServerComponents と App Router 1. 2. 3. 4. 5.
  31. 静的 HTML JS エンジン SPA の課題①:クローラー クローラー Web サーバ コンテンツとしては空

    コンテンツがないから インデックスできない JS に対応した クローラー インデックスが遅れて しまう!
  32. 静的 HTML DOM JS SPA の課題②:初期表示 Web サーバ ブラウザ レンダリング

    JSON API サーバ DB (CSR) コンテンツとしては空 (SSR 不要) コンテンツは 空 <script src=”...” /> コンテンツは 存在 LCP が遅 い!
  33. ※ Core Web Vitals 2.5 s 4 s 100 ms

    300 ms 0.1 0.25 初期画面のうち、最大の領 域を占めるコンテンツが表 示されるまでの時間 Large Contentful Painting First Input Delay 初回のユーザー操作・入力 が可能になるまでの時間 視覚的な安定性を計測する ためのレイアウトシフト数 (いわゆるガタツキ) Cumlative Layout Shift LCP FID CLS
  34. SPA の課題 MPA (クラシック SSR)からの移行コスト SEO 対策が困難 10 年代半ばのクローラーは JS非サポート

    現在は Google など JS サポートクローラーあるが... インデックス遅い OGP 対応困難・通信環境に依存 初期表示が遅い(LCP / FCP) 最初に読み込まれる HTML が空
  35. HTML DOM JS JS Pre-rendering Node.js ブラウザ レンダリング JSON API

    サーバ DB (CSR) コンテンツを含む コンテンツあり <script src=”...” /> インタラクション LCP が速い INP が遅 い! JSON 同じコードベース
  36. SPA(CSR + Pre-rendering) 最初に配信される HTML にコンテンツをPre-render Pre-rendering には CSR と同じコードベースを利用

    例: React, VueJS, etc. Pre-rendering には Node.js を用いる renderToString(<App />)。DOM 操作の代わりに HTML 文字列 「初期表示が遅い」問題を解決 初期表示後は通常通り CSR と同じように動作
  37. ページ単位で事前レンダリングの種類を選択 SSR( Server-side Rendering ) HTTP リクエストごとに JS ランタイム必須。renderToString(<App />)

    SG( Static Generation ) ビルド時にPre-rendering JS ランタイム不要 ISR ( Incremental Static Regeneration ) SSG + SSR( Pre-renderingとオンデマンド ) revalidate: 5[s] JS ランタイム必須 Pre-rendering の種類 MPA の クラシックSSR と 区別する場合は SSR with Hydration と呼ばれる
  38. Next.js の登場 The React Framework for the Web Web のための

    React フレームワーク 開発元は Vercel 火曜に障害起こしがちなのなんとかしてくれ フルスタック FW 界を統一しようとしてる Rails などと同じ土俵で戦っている 当初は SSR を提供するだけのものだった 今では Zero Config や Routing など React がカバーしきれない部 分を補完
  39. ✅ アジェンダ  JavaScript の発展と Ajax  SPAの流行と各 FW の乱立  React の登場と宣言的

    UI  Next.js の登場と Pre-rendering  React ServerComponents と App Router 1. 2. 3. 4. 5.
  40. Pre-rendering の問題点 SSR 実行時の時間とコスト サーバーからレスポンス返ってくるまでの時間が長い TTFB( Time to First Byte)

    が長い 特に データ取得が必要なページ・更新頻度高いページなど... SSG / ISR では根本的解決にはならない INP / TTI が遅い JS がロードされるまで「見えるのに押せない」 LCP は速いが、TTI がおっそい Hydration までの時間と Hydration 自体の時間 これの解が React Server Components 1. 2.
  41. Pre-rendering の問題点 SSR 実行時の時間とコスト サーバーからレスポンス返ってくるまでの時間が長い TTFB( Time to First Byte)

    が長い 特に データ取得が必要なページ・更新頻度高いページなど... SSG / ISR では根本的解決にはならない INP / TTI が遅い JS がロードされるまで見えるのに押せない LCP は速いが、TTI がおっそい。 Hydration までの時間と Hydration 自体の時間 これの解が React Server Components 1. 2.
  42. Service Worker Storage Local Cache CDN キャッシュ App memory cache

    db ブラウザ CDNエッジ アプリケーション
  43. Service Worker Storage Local Cache CDN App memory cache db

    なるべくユーザーに近い位置でキャッシュして高速に返却することで、 パフォーマンス向上させる
  44. Pre-rendering の問題点 SSR 実行時の時間とコスト サーバーからレスポンス返ってくるまでの時間が長い TTFB( Time to First Byte)

    が長い 特に データ取得が必要なページ・更新頻度高いページなど... SSG / ISR では根本的解決にはならない INP / TTI が遅い JS がロードされるまで見えるのに押せない LCP は速いが、TTI がおっそい これの解が React Server Components 1. 2.
  45. JavaScript is the web's CO2. 肥大化するクライアント JS SPA などの技術がコモディティ化 JS

    は Web の CO2!?!? さらに ハイドレーションの問題もある hydrateRoot(document.getElementById('root'), <App />); SSR は同じ React アプリケーションをサーバとクライアントの 2ヶ所でレンダリングする 無駄が多い クライアント側で実行しなきゃいけない JS の量は減っていない
  46. Server Component + Client Component HTML + Client Component HTML

    + JavaScript Client (ブラウザ) React Server Components Server Stage0 Stage1 実態としては 仮想 DOM をシリ アライズしたもの
  47. React Server Components 多段階計算 → バンドルサイズ↓ Reactアプリケーションの中に、サーバーで実行される部分とクライ アント側で実行される部分が混在 Stage0 =

    サーバー側、Stage1 = クライアント側 Stage0 のプログラム → Stage1 のプログラム → 出力結果 クラシカルSSR + jQuery との類似性 「PHP の再来」。螺旋 Stage0 = <div><%= @us er.name %></div> Stage 1 には HTML + JavaScript が出力される RSC が進化しているのは2つの段階が両方ともReactである点
  48. Server Component + Client Com ponent HTML + Client C

    omponent Client (ブラウザ) React Server Components(+ SSR) Server Stage 0 HTML Rendering JavaScript Stage 1 Hydration
  49. HTML M C V DOM JS テンプレート Webサーバ 依 存

    技術の螺旋 APサーバ ブラウザ DB data React へ統一
  50. App Router Next.js 13.4 から stable app/配下が Server Componentとして扱われる テンプレートエンジンとして考えればこの扱いも納得がいく

    サーバーサイド用のテンプレートを用いるときは生で使うより FW に乗せて使うことが多いよね! Client Component はオプトイン ほかにもキャッシュ周りやParallel Routes,  ServerActionsといった機能も追加されている
  51. 参考資料 React 研修 https://speakerdeck.com/recruitengineers/react-2023 Next.jsから学ぶWebレンダリング ~React誕生以前からApp Router with RSCまでの流れ~ https://zenn.dev/suzu_4/articles/2e6dbb25c12ee5

    一言で理解するReact Server Components https://zenn.dev/uhyo/articles/react-server-components-multi-stage#react-server- components モダンウェブフロントエンド勉強会を開催しました https://techlife.cookpad.com/entry/2022/06/21/130736 SPA化するMPAとMPA化するSPA https://gihyo.jp/article/2022/11/tfen001-mpa_spa