【key-front】より速いWEBを目指すNext.js / nextjs-make-the-web-fasterを読んでみた
モチベーション
- 毎週金曜日Slackのkey_frontチャンネルでハドル機能を使いお題に対してメンバー同士ディスカッションをする時間を15〜30分程度設けている
- 今回は「より速いWEBを目指すNext.js / nextjs-make-the-web-faster」の共有会
- ファシリテーターは筆者なので、事前に読み込んで気になった点などをスクラップに投げていく
- 開催日は9/1(金)で最終的に議事録として結論をまとめる
補足
- 前回「Next.jsのSPA」に触れていたので今回はNext.jsのコア機能にフォーカスを当てる
- Next.js13は次回取り上げるので、最新の情報とは違うかもしれないので注意
参考資料
メモ1
今回の資料から取り上げるのは下記の3点。補足なども適宜摘みながら見ていく。
- code-splitting
- pre-fetching
- pre-rendering
適宜補足を入れながら摘んでいく
code-splitting
SPAの課題であるページ単位でのスクリプト分割は自動でやってくれる
Next.jsの様なフレームワークがなかったころSPAは単一のchunkに統合されてしまうなど、適切にchunk分割されているとは限りませんでした。
SPA(CSRのみ)の場合はどうすればいいのか?
もともとはLaravel⇄Blade⇄Vue.jsのモノレポ案件でpage.js使ってchunkを分ける実装を知っていてメリットを理解していた。なのでSPA案件を始めるにあたってコード分割は早めの段階で実装に取り組むようキャッチアップしていた。
React Router・React.lazy・React.Suspenseでルート単位でコードを分割(code-splitting)するができる
React.lazyは現在default exportのみサポートしているがタイプセーフなnamed exportでもcode-splittingできる(検証済み)
適宜補足を入れながら摘んでいく
pre-fetching
はじめに
初めはgetServersidePropsやgetStaticPropsのこと(pre-rendering)かと思っていたが、そうではなくnext/linkの裏側の挙動についてのことだった
prefetchのメリット
Prefetchは高速なナビゲーションを実現し、視覚的安定性に貢献します
→具体的にはどうやって?
ここで<Link>
コンポーネントと前回のkey-frontで取り上げた直接アクセス・SPAナビゲーションに備え「両方」用意される
に繋がる。色々と後述するが両方用意されるがその出しわけのトリガーは<Link>
コンポーネントぽい。
<Link>
を使っていると、Pre-renderingで事前に作成されたHTMLでも、遷移時はJSによる画面切り替えを実施してくれます。
前回のkey-frontでも取り上げた直接アクセス・SPAナビゲーションに備え「両方」用意される
の補足をする
実際にnetworkタブで検証すればわかるが次の記事で画像ありで説明がされていた。<Link>
を使ってナビゲーションするか初回描画で生成するものが異なることがわかる。
適宜補足を入れながら摘んでいく
SWR, react-queryのprefetchとnext/linkのprefetch
next/linkのprefetchはSWRのprefetchと同等の効果がある
SWR, react-queryの場合
-
トリガーがない(以下参照)
-
関係ないけどtakepepeさんはnext/linkに相当するものを作ってた(next/linkと同じように振る舞うcomponent)
これら課題解決のため、できあがったものが以下の
<Link>
コンポーネントです。通常のnext/link
挙動を残しつつ、props を拡張しました。SWR の Programmatically Prefetch を、next/link
の ISR Prefetch と同様に Intersection Observer・マウスオーバーで発火しています。 -
普通に考えたら遷移したページで次に遷移できる箇所をprefetchする感じになると思う。が過度なprefetchに繋がりそう
next/linkの場合
-
next/linkはリンク先のページにgsspが定義されている場合マウスオーバーをトリガーに遷移先のgsspを実行する
(資料参照) -
next/linkは大味なprefetchがデフォルトとなので注意が必要とのこと
-
公式ドキュメントではviewportに入ったらpre-fetchingとのこと(検証済み)→これは仕様が変わったってこと?
next/linkはバックグラウンドでページ(hrefで示される)をプリフェッチします。これはクライアントサイドナビゲーションのパフォーマンスを向上させるのに有用である。ビューポート内のすべての <Link /> が(初期状態またはスクロールによって)プリロードされます。
補足
router.pushでpre-fetching
適宜補足を入れながら摘んでいく
CSR・SSR・SSG・ISR
- CSR:空のHTMLを返してブラウザでレンダリングする
- SSR:リクエストごとにサーバサイドでHTMLを組み立ててブラウザに返す
- SSG:ビルド時にHTMLを組み立ててリクエスト時にそのHTMLをブラウザに返す
- ISR:stale-while-revaildateしてくれるSSG
上記は調べれば資料がたくさん出てくるので割愛する。どちらかと言うと今まで勘違いしていたことや用語などにフォーカスする
メモ2
- 「pre-rendering」は「事前レンダリング」と言われている
- 事前レンダリングで出てくる「中身が空のHTML」や「最小限のJSコード」は次のことを指している
// 中身が空のHTML
<html>
<head>
<title>sample</title>
</head>
<body>
<div id="app"></div>
<script src="/js/bundle.js"></script> //「最小限のJSのコード」
</body>
</html>
適宜補足を入れながら摘んでいく
メモ3
自分がNext.jsに対して誤解していたことと同じ内容だったのでメモ。
私はnextjsを学んでいて、ある場所ではnextjsは最初のページだけをプリレンダリングすると書いてあり、他の場所ではnextjsはデフォルトですべてのページをプリレンダリングすると書いてあるので、どちらが本当なのか理解できません。
恐らく上記の質問者は自分と同じことを考えていて、自分が疑問に思ったのはPre-renderingでよく見る次の説明。
Pre-renderingは事前にHTMLを生成することです。Next.jsではデフォルトで全ページをPre-rendering
してくれています
誤解1
デフォルトで全ページをPre-renderingされている(HTMLを生成している)のかと思っていて、それはつまりMPAではないのかとずっと思っていた。
けれどこの説明は事実ではあるけれど色々と補足情報が足りていないと調査を進めていく中で分かった。
誤解2
またSPAがSSRやSSGと同等に比較されている記事も見ていてそもそも視点がずれていたこともある。SPAがCSRっぽい説明だったりというのもあったような気がする。
けれどこれもよく見れば補足があったりと自分が詳細まで目を通せなかったのが原因かもしれない。
補足
リクルートの研修資料と同じ内容だけどより詳細に違う角度から説明しており、非常に分かりやすかった。
リクルートの研修資料では直接アクセス・SPAナビゲーションに備え「両方」用意される
と説明されていたが下記の方がもっと具体的でわかりやすいかも
Next.jsのレンダリングは、大きく分けて、ページの再読み込み時、画面遷移時の2つに分かれる。
実際に挙動を見るDEMOアプリもあるのでリクルートの研修資料でざっと大枠を理解してから記事を見るのがおすすめ。
後で肉付けする
一旦まとめ
ReactとNext.jsは次のように分類することができる
- React = SPA(CSRのみ)
- Next.js = SPA(CSR + 事前レンダリング)
Next.jsはReactのつらみを解消してくれる(課題解決をしてくれる)
-
ルーティング(Reactデフォルトではない、react-routerで可能)
→Next.jsではFile-Based-Routingになる -
コード分割(Reactデフォルトではない、react-router・React.lazy・React.Suspenseで可能)
→Next.jsでは自動でcode-splittingをする -
初期描画のパフォーマンス
→Next.jsではpre-renderingで初期描画の改善が可能 -
SPAナビゲーション(client-dide-navigation)
→Next.jsではpre-fetchingをして本来あるSPAの強みを活かす =厳密にはcode-splitting(JSコードの自動分割)とpre-fetching(コンポーネントの事前生成)という技術を用いる
他にも色々あるが割愛します。
Next.jsに思っていた誤解
-
SPA・SSR・SSGは同じ括りではない
→SPAの枠の中にSSR・SSGがあるイメージ。そもそもSSR・SSGはレンダリングで、ここのSPAはCSRを指していると思っていてこれがこんがらがる要因ぽい。 -
Next.jsではデフォルトで全ページをpre-renderingする = MPAではない
→初期描画はHTMLを表示するがSPAナビゲーション(厳密にはnext/linkなどの遷移)ではJSONでDOMの書き換えをする
あとはkey-front当日に結論(今回の内容の感想など)を出す
議事録_20230901
- 9/1(金)に実施
- 結論を出すコンテンツではなかったため特に結論はなし
- 参加人数は6名(以下エビデンス)
- 本当は次回React.js18やNext.js13周りをやろうかと思っていたが先にreact-testing-libraryを実施する