このドキュメント、はNext.jsバージョン9.3以上を対象としています。 古いバージョンのNext.jsを使用する場合は、過去のドキュメントを参照してください。
Next.js では、ページ(page)というのは pages
ディレクトリ内の .js
, jsx
, .ts
, .tsx
ファイルから export
されたReact コンポーネント のことです。
それぞれのページのルーティングはファイル名によって決まります。
例: 以下のような React コンポーネントを export
する pages/about.js
というファイルを作成すると、/about
へとアクセスできるようになります。
function About() {
return <div>About</div>;
}
export default About;
Next.js の pages は動的なルーティングをサポートしています。
例えば、pages/posts/[id].js
というファイルを作成すると、posts/1
, posts/2
などにアクセスできます。
動的なルーティングについてさらに知るには、動的なルーティングのドキュメント をご覧ください。
通常、Next.js はそれぞれのページを事前にレンダリングします。 つまり、クライアント側の JavaScript でページ全体を生成する代わりに、それぞれのページの HTML をあらかじめ生成します。 プリレンダリングは優れたパフォーマンスと SEO をもたらします。
生成されたそれぞれの HTML には、そのページの生成に最低限必要な JavaScript コードが関連事項づけられています。 ページがブラウザから読み込まれると、JavaScript コードが走りページをインタラクティブなものにします。(この処理はハイドレーションと呼ばれています。)
Next.js ではプリレンダリングに関して静的生成(Static Generation)とサーバーサイドレンダリング(Server-side Rendering)の 2 つの方式が利用可能です。 これらの違いは、HTML をいつ生成するかです。
重要なのは、Next.js ではどちらのプリレンダリング方法を用いるかを、それぞれのページに対して選ぶことができるということです。 つまり、ほとんどのページには静的生成を用い、残りのページにはサーバーサイドレンダリングを用いるといった、"ハイブリッド"な構成で Next.js アプリを作ることができます。
パフォーマンスの観点から、サーバーサイドレンダリングよりも静的生成を用いることを推奨しています。 静的に生成されたページは CDN によりキャッシュされ、パフォーマンスが高まります。ただし、サーバーサイドレンダリングを選択せざるを得ない場合もあります。
クライアントサイドレンダリングも静的生成やサーバーサイドレンダリングと同様にいつでも用いることができます。 つまり、ページの特定部分をクライアント側の JavaScript で丸ごとレンダーしても良いです。 これについてさらに知りたい場合には、データ取得のドキュメントをご覧ください。
ページを静的生成するということは、そのページの HTML をビルド時に生成するということです。
本番用のアプリケーションでは、next build
を実行すると HTML が生成されます。
この HTML はリクエストの度に再利用され、CDN によりキャッシュが可能です。
Next.js では、外部データの取得の有無に関わらずページの静的生成が可能です。それぞれのケースについて見ていきましょう。
通常、Next.js はデータを取得せずに静的生成によってページをプリレンダリングします。以下がその例です。
function About() {
return <div>About</div>;
}
export default About;
このページは外部からのデータ取得が必要ないことに留意してください。 このような場合、Next.js はビルド時に 1 ページ当たり 1 つの HTML ファイルを生成します。
ページによってはプリレンダリング時に外部のデータを取得しなければならない場合があります。 これには以下 2 つのシナリオのいずれかあるいは両方が考えられます。 それぞれのケースにおいて、Next.js の提供する以下の関数を用います。
getStaticProps
を用いてください。getStaticPaths
を用いてください(通常、getStaticProps
と合わせて用いられます)。例: ブログのページが CMS (コンテンツ管理システム)から投稿した記事を取得する必要がある場合。
// TODO: ページをプリレンダリングする前に、
// (APIのエンドポイントをコールして)`posts`を取得する必要あり
function Blog({ posts }) {
return (
<ul>
{posts.map(post => (
<li>{post.title}</li>
))}
</ul>
);
}
export default Blog;
プリレンダリング時にデータを取得するために、Next.js では getStaticProps
と呼ばれる async
関数を同じファイルから export
します。
この関数はビルド時に呼ばれ、取得されたデータをページのプリレンダリング時の props
に渡します。
function Blog({ posts }) {
// 記事のレンダー
}
// この関数はビルド時に呼ばれる
export async function getStaticProps() {
// 投稿記事を取得する外部APIエンドポイントをコール
const res = await fetch('https://.../posts');
const posts = await res.json();
// { props: posts }を返すことで、ビルド時にBlogコンポーネントが
// `posts`をpropとして受け取れる
return {
props: {
posts
}
};
}
export default Blog;
getStaticProps
の動作についてさらに知るためには、データ取得のドキュメントをご覧ください。
Next.js では動的なルーティングによるページの生成が可能です。例えば、id
に紐づくブログ投稿を表示するためには、pages/posts/[id].js
というファイルを作成します。
これにより、posts/1
にアクセスすると id: 1
の投稿内容が表示されます。
動的ルーティングについてさらに知るためには、動的ルーティングのドキュメントをご覧ください。
しかしながら、どの id
をビルド時にプリレンダリングするかが外部データに依存する可能性があります。
例: データベースに id: 1
のブログ記事のみが追加された場合を考えてみましょう。この場合、ビルド時にプリレンダリングによってページを生成したいのは posts/1
のみです。
後になって id: 2
のブログ記事を追加するとしましょう。今度はビルド時に posts/2
もプリレンダリングする必要があります。
つまり、プリレンダリングするページのパスは外部のデータに依存します。外部データに依存するパスを扱うために、Next.js では getStaticPaths
という async
関数を export
します。(今回の場合、pages/posts/[id].js
に追加します。)
// この関数はビルド時に呼ばれる
export async function getStaticPaths() {
// 記事を取得する外部APIのエンドポイントをコール
const res = await fetch('https://.../posts');
const posts = await res.json();
// 記事にもとづいてプリレンダするパスを取得
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// 設定したパスのみ、ビルド時にプリレンダ
// { fallback: false } は、他のルートが404になるという意味
return { paths, fallback: false };
}
pages/posts/[id].js
は、id
のブログ記事の内容を取得してページをプリレンダリングするために、getStaticProps
も合わせて export
する必要があります。
function Post({ post }) {
// 記事のレンダー
}
export async function getStaticPaths() {
// ...
}
// この関数もビルド時に呼ばれる
export async function getStaticProps({ params }) {
// `params`は`id`の記事内容を含む
// ルートが/posts/1とすると、params.idは1となる
const res = await fetch(`https://.../posts/${params.id}`);
const post = await res.json();
// propsを通じてpostをページに渡す
return { props: { post } };
}
export default Post;
getStaticPaths
の動作についてさらに知りたい場合には、データ取得のドキュメントをご覧ください。
ページは一度だけビルドしてしまえば CDN によって配信できるので、(データ取得の有無に関わらず)可能な限り静的生成を推奨しています。 これにより、それぞれのリクエストに対してサーバー側で HTML を生成するよりもずっと高速になります。
静的生成は以下のような様々なページに対して行うことができます。
「このページはユーザのリクエストより前にコンテンツを準備しておくことが可能か?」と自分自身に問いかけてみてください。 もし答えが YES なら、静的生成を選択すべきでしょう。
一方、ユーザーのリクエストよりも前にページの内容を準備できない場合、静的生成は推奨されません。 ページに含まれる情報が頻繁に更新され、リクエストの度に内容が変わることもあり得るでしょう。
このような場合には、以下の方法をとることができます。
"SSR"や"ダイナミックレンダリング"とも呼ばれます。
サーバーサイドレンダリングを用いると、ページの HTML がリクエストの度に生成されます。
サーバーサイドレンダリングを使うためには、getServerSideProps
と呼ばれる async
関数を export
する必要があります。この関数はリクエストごとにサーバー側で呼ばれます。
例えば、ページの表示に用いるデータ(外部の API から取得する)が頻繁に更新される場合を考えましょう。この場合、以下のように getServerSideProps
を追加することで、データを取得して Page
に渡す処理を行うことができます。
function Page({ data }) {
// 記事のレンダー
}
// この関数はリクエストのたびに呼ばれる
export async function getServerSideProps() {
// 外部のAPIからデータを取得
const res = await fetch(`https://.../data`);
const data = await res.json();
// propsを通してdataを渡す
return { props: { data } };
}
export default Page;
見ての通り、getServerSideProps
は getStaticProps
とよく似ています。両者の違いは、getServerSideProps
がビルド時ではなくリクエストの度に呼ばれることです。
getServerSideProps
の動作についてさらに知りたい場合には、データ取得のドキュメントをご覧ください。
Next.js のプリレンダリングの方法として、以下の 2 つについて説明しました。
export
するか、getStaticProps
(必要であれば getStaticPaths
も)を export
してください。
ユーザーからのリクエストの前に, ページをプリレンダリングできるということは素晴らしいことです。クライアントサイドレンダリングと併用することで、追加のデータもレンダリングできます。getServerSideProps
を export
してください。
サーバーサイドレンダリングは静的生成に比べて動作が遅くなるため、どうしても必要な場合にのみ使用してください。以下のセクションを次に読むことをお勧めします。