Next.js Learn メモ

Next.js 公式の学習コースが公開されたので、進めてみる。
Next.js Learn

フォント最適化
next/font
にあるフォントをエクスポートして、クラス名に代入して使う。

MUIのデフォルトのフォント使ってたような気がするから、フォントをあまり気にしたことなかったな。


layout コンポーネントを使用することで、
画面遷移時に、ページコンポーネントのみ部分的に再レンダリングされる。(Partial Rendering)

Setting Up Your Database

とりあえず、Vercel の画面から、Postgre DB 作成して、環境変数をローカルにコピーして、シードデータを簡単に入れることができた。

Fetching Data

抜粋
There are a few benefits to fetching data with React Server Components:
- Server Components execute on the server, so you can keep expensive data fetches and logic on the server and only send the result to the client.
- Server Components support promises, providing a simpler solution for asynchronous tasks like data fetching. You can use async/await syntax without reaching out for useEffect, useState or data fetching libraries.
- Since Server Components execute on the server, you can query the database directly without an additional API layer.

Server Component でフェッチが複数回発生する場合。
順次的に関数が実行されるため、意図しないパフォーマンス問題が発生するかもしれないので注意。

Promise.all
と Promise.allSettled
の違い
Promise.all
と Promise.allSettled
は、JavaScriptのPromiseを操作するための2つの異なるメソッドです。それぞれの違いは以下の通りです:
-
Promise.all
:- すべてのPromiseが成功(resolved)した場合、単一の成功したPromiseを返します。一方、どれかのPromiseが失敗(rejected)した場合、最初に失敗したPromiseのエラーを返します。つまり、成功と失敗の結果がユニークな1つのPromiseにまとまります。
-
Promise.all
を使用すると、複数の非同期操作が全て成功しなければならず、一つでも失敗すると全体が失敗します。
例:
const promises = [promise1, promise2, promise3];
Promise.all(promises)
.then(results => {
// 全てのPromiseが成功した場合、resultsに成功した値が格納される
})
.catch(error => {
// どれかのPromiseが失敗した場合、errorに最初の失敗のエラーが格納される
});
-
Promise.allSettled
:- すべてのPromiseが成功したか失敗したかにかかわらず、各Promiseの結果(成功した場合は値、失敗した場合はエラー)を保持する新しいPromiseを返します。つまり、各Promiseの結果を個別に取得できます。
-
Promise.allSettled
を使用すると、全ての非同期操作の結果を確認でき、失敗しても全体が失敗しないため、一部の操作が失敗しても残りの操作を評価できます。
例:
const promises = [promise1, promise2, promise3];
Promise.allSettled(promises)
.then(results => {
results.forEach(result => {
if (result.status === 'fulfilled') {
// result.valueに成功した値が格納される
} else if (result.status === 'rejected') {
// result.reasonに失敗のエラーが格納される
}
});
});
要するに、Promise.all
は全てが成功するか、一つでも失敗したら失敗する一括処理に適している一方、Promise.allSettled
は全ての結果を個別に取得し、失敗しても全体を中断しない場合に便利です。どちらを選ぶかは、具体的な使用ケースに依存します。
by ChatGPT先生

Promise.all で複数の非同期処理を一括に処理することで、表示までのパフォーマンスは向上する。
しかし、その中で遅い関数があった場合は?とある。確かにそうだな。

Static and Dynamic Rendering

静的レンダリングでは、ビルド時にフェッチとレンダリングを行い、結果をCDNに配信する。
CDNにビルドがキャッシュされるメリットは以下。
- Faster Websites - Prerendered content can be cached. This ensures that users around the world can access your website's content more quickly and reliably.
- Reduced Server Load - Because the content is cached, your server does not have to dynamically generate content for each user request.
- SEO - Prerendered content is easier for search engine crawlers to index, as the content is already available when the page loads. This can lead to improved search engine rankings.
ブログや製品ページなどの静的サイトでは有効だが、更新の多いダッシュボードには適さない。

動的レンダリングでは、ユーザーからのリクエストがあった時点で、サーバーがレンダリングを行う。
メリットは以下。
- Real-Time Data - Dynamic rendering allows your application to display real-time or frequently updated data. This is ideal for applications where data changes often.
- User-Specific Content - It's easier to serve user-specific content, such as personalized dashboards or user profiles, through dynamic rendering, as the data is updated based on user interaction.
- Request Time Information - Dynamic rendering allows you to access information that can only be known at request time, such as cookies or the URL search parameters.

サーバーコンポーネントやデータ取得関数の内部で、next/cache
の、unstable_noStore
を使うと、静的レンダリングを省略できる。

Streaming

ストリーミングとは、ルートを小さな "チャンク "に分割し、準備ができ次第、サーバーからクライアントに順次ストリーミングするデータ転送技術である。

app ディレクトリでは、ページのロード時に loading.tsx の内容を表示してくれるので、より早くユーザーにUIを表示することができる。

括弧()を使用して新しいフォルダを作成すると、その名前はURLパスに含まれない。

局所的にコンポーネント単位でローディングを表示させたいときは、<Suspence>でコンポーネントを囲み、fallback にloading コンポーネント を指定してあげればよい

app router ではフェッチはコンポーネント単位で行ったほうがいいのか。
page router で Container/Presenter パターンで、ページ単位にContainer コンポーネントとそれに対応する graphql をコロケーションするような実装だと、ローディングの状態を細かく表現できないし。

というかServer Componentで直接フェッチするようになるから、app routerではgraphql は使わない(使えない)ってことなのか?

Adding Search and Pagination

Server Component は、URLのパラメータに状態を持っておくのが基本のよう。
これまで useState とか recoil 使って Client Side で状態を持つことが多かったけど、そのあたりのアプローチが異なる。

Mutating Data

revalidatePath
は、指定されたページのキャッシュをクリアしてサーバーにリクエストする関数。
データの更新後に実行するとよしなにやってくれそう。