これはNext.jsの公式チュートリアルの8. Static and Dynamic Rendering に関するメモです
前章のメモ
Next.jsの公式チュートリアルの該当ページ
学ぶこと
- 静的レンダリングとは何か?、どのようにパフォーマンスを向上させるか?
- 動的レンダリングとは何か?、いつ使うのか?
- ダッシュボードを動的にするためのアプローチ
- 遅いデータフェッチが何を起こすのか?
静的レンダリングとは何か?
サーバーコンポーネントにおけるデフォルトのレンダリング方法で
アプリのビルドやrevalidateの際にデータを取得&レンダリングすること。
ビルド時にレンダリングしたものはCDNにキャッシュされます。
ユーザに対してはキャッシュされた結果が返されるので下記のメリットがあります。
常に最新のデータを表示できるわけではないので、ブログ記事や商品ページといった
比較的更新頻度が低く、どのユーザにも同じように表示されるページに適しています。
動的レンダリングとは何か?
ユーザのリクエストごとにレンダリングすること。
ダッシュボードやSNSのタイムラインなど
更新頻度が高いページやユーザごとに異なる表示となるページに適しています
ダッシュボードを動的にする
サーバーコンポーネントはデフォルトで静的レンダリングを使用します。
では、動的レンダリングを使用するにはどうすればよいでしょうか?
unstable_noStore というNext.js のAPIを呼び出すことで動的レンダリングにします
早速、前章で使用した /app/lib/data.ts で使ってみましょう!
とはいえ、next/cache から unstable_noStore をインポートして実行するのみ。
1 2 3 4 5 6 7 8 9 10 11 |
// 一部抜粋 import { unstable_noStore as noStore } from 'next/cache'; export async function fetchRevenue() { // Add noStore() here to prevent the response from being cached. // This is equivalent to in fetch(..., {cache: 'no-store'}). noStore(); //... } |
みたいな感じで
- fetchLatestInvoices
- fetchCardData
- fetchFilteredInvoices
- fetchInvoicesPages
- fetchFilteredCustomers
- fetchInvoiceById
にもnoStore()を記述します
遅いデータフェッチを再現する
ダッシュボードを動的レンダリングにできました!
ただ、前章でも触れた1つでもデータ取得に時間がかかるものがあった場合どうなるでしょうか?
実際にアプリケーションを使用して試してみます。
/app/lib/data.ts のfetchRevenue関数内のコメントを↓のように外していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// 一部抜粋 export async function fetchRevenue() { // Add noStore() here to prevent the response from being cached. // This is equivalent to in fetch(..., {cache: 'no-store'}). noStore(); try { // Artificially delay a response for demo purposes. // Don't do this in production :) console.log('Fetching revenue data...'); await new Promise((resolve) => setTimeout(resolve, 3000)); const data = await sql<Revenue>`SELECT * FROM revenue`; console.log('Data fetch completed after 3 seconds.'); return data.rows; } catch (error) { console.error('Database Error:', error); throw new Error('Failed to fetch revenue data.'); } } |
Promiseインスタンス+setTimeout を使用することで指定した時間だけ待つことができます
引数に3000msと指定しているので3秒待つことになります。
つまり、この関数の処理に3秒+αかかります。
ローカルサーバを起動して、http://localhost:3000/dashboard にアクセスすると
表示に時間がかかることがわかると思います
curlコマンドで時間を計測してみると。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 3秒待つ処理を入れた前 $ curl -w"time_total: %{time_total}\n" -o /dev/null http://localhost:3000/dashboard % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 40461 0 40461 0 0 64364 0 --:--:-- --:--:-- --:--:-- 64325 time_total: 0.628620 // 3秒待つ処理を入れた後 $ curl -w"time_total: %{time_total}\n" -o /dev/null http://localhost:3000/dashboard % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 40461 0 40461 0 0 8638 0 --:--:-- 0:00:04 --:--:-- 11620 time_total: 4.683759 |
約0.6秒と約4.7秒なのでパフォーマンスが大幅に異なりますね
なので、
Q. 1つでもデータ取得に時間がかかるものがあった場合どうなるでしょうか?
A. 動的レンダリングでは、アプリケーションの速度は最も遅いデータ取得速度と同じになる。
次章でこの課題を解決する方法を見ていきます
次章のメモ
コメント