【Next.js】prefetch 時に fetch がどこまで動くのかを検証した
モチベーション
Next.js の App Router で
- 全ページに dynamic rendering を強制している
- loading.js を一つも配置していない
という状況のとき、prefetch(プリフェッチ)で fetch によるデータの取得が行われるのかの理解が曖昧だったため改めて検証した。
環境
- Next.js v15.0.1 App Router
検証に使用したソースコードは下記に配置した。
https://gitlab.com/k1350/nextjs-15-prefetch-test
Link コンポーネントの prefetch 以外の設定はすべて v15.0.1 のデフォルト設定で検証した。
検証
検証パターンについて
今回の検証では Link コンポーネントの prefetch を対象とする。
prefetch が取り得る値は
- null
- true
- false
の三種類だが、false の場合は prefetch が発生しないので除外する。
また prefetch = null のときの説明は
Prefetch behavior depends on whether the route is static or dynamic. For static routes, the full route will be prefetched (including all its data). For dynamic routes, the partial route down to the nearest segment with a
loading.js
boundary will be prefetched.
なのだが、Route Segment Config で dynamic を指定すれば static routes にも dynamic rendering を強制することが可能である。
今回の検証中、実際に dynamic = "force-dynamic"
を指定することにより、dynamic routes かどうかではなく dynamic rendering かどうかによって挙動が変わるということを確認できたので、static rendering / dynamic rendering という表現で話を進める。
Dynamic rendering の場合は loading.js ファイルの配置によって挙動が変わる。
loading.js
がある場合の挙動は説明からわかるが、loading.js
が一つも無かったら一切 fetch が動かないという理解でいいのか? という点が気になっているため、今回は loading.js
の有無でパターン分けする。
まとめると今回検証するパターンは下記である。
prefetch = null | prefetch = true | |
---|---|---|
static rendering | ? | ? |
dynamic rendering(loading.js あり) |
? | ? |
dynamic rendering(loading.js なし) |
? | ? |
検証結果
まず前提となるが、Client Component の useEffect 内での fetch は、ページを実際に表示したときに初めて行われる。
従って、以下はすべて Server Component の話である。
また Suspense で囲っているかどうかが影響するかも検証したが、影響しなかった。よって以下は Server Components 内での fetch すべてに当てはまる。
Static rendering
ビルド時にすべてのセグメントで fetch によるデータ取得が行われる。
Prefetch 時に改めてデータ取得が行われることはない。
Dynamic rendering(prefetch = true)
loading.js
の有無によらず、prefetch 時にすべてのセグメントで fetch による取得が行われる。
Dynamic rendering(prefetch = null)
下記のようなファイル配置なら prefetch 時に layout.tsx
内の fetch のみ実行される。
app
|-dynamic
|-layout.tsx
|-[id]
|-loading.tsx
|-page.tsx
一方下記のように loading.js
が一つも配置されていない場合、prefetch 時に fetch によるデータ取得は一切行われない。
app
|-dynamic
|-layout.tsx
|-[id]
|-page.tsx
通常、loading.js
は Suspense とセットで使用することが多いと思う。
しかし prefetch がどのセグメントまで行われるかに関しては loading.js
がどこに配置されているかで決まり、Suspense が使われているかどうか(=loading.tsx
の中身が表示され得るかどうか)は関係ない。
まとめ
prefetch = null | prefetch = true | |
---|---|---|
static rendering | ビルド時に全部 | ビルド時に全部 |
dynamic rendering(loading.js あり) |
loading.js が最初に配置されているセグメントの親まで |
全部 |
dynamic rendering(loading.js なし) |
fetch しない | 全部 |
結論としては、
- 全ページに dynamic rendering を強制している
-
loading.js
を一つも配置していない
というケースでは prefetch 時に fetch によるデータ取得は一切行われない。
もしデータ取得をしてほしい場合、Suspense を使用していなくても、適切なセグメントに loading.js
を配置する必要がある。
ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion