Next.jsとは
Next.jsは、ReactをベースにしたJavaScriptフレームワーク。
ウェブ開発を効率化し、パフォーマンスを向上させるためのツールとして非常に人気。
Next.jsにおけるレンダリングについて
Reactでは1つのレンダリング方法に依存するのに対し、Next.jsでは様々なレンダリング方法を選択することができ、それがNext.jsの強みでもあります。
Reactの基本的なレンダリング
Reactは主に Client Side Rendering(CSR) を中心に動作します。Reactでは、ブラウザがHTMLを受け取った後、JavaScriptが実行されてDOMにコンポーネントが描画されます。
Reactのレンダリングの流れ(CSR)
- クライアントからリクエストが送られる。
- サーバーから空のHTML、CSSとJavaScriptが送られる。
- ブラウザでJavaScriptが実行され、Reactが仮想DOMを構築。
- 仮想DOMをもとに実際のDOMが更新され、UIが表示される。
CSRではページ遷移時にサーバーにリクエストを送らず、既に読み込んだJavaScriptで処理するため、ネットワークの遅延がほぼ発生せず、画面遷移が高速になります。いわゆる SPA(Single Page Application) といわれるものです。
一方で、初回読み込み時にデータを一括して取得するので、初期表示が遅くなりがちです。
また、サーバーから返されるHTMLはほぼ空の状態であるため、検索エンジンのクローラー(Googlebotなど)が「このページには何もない」と判断してしまうリスクがあるため、SEOの面でSSRやSGに比べると不利になる可能性があるといったデメリットもあります。
Reactコード例 (CSR)
import { useState, useEffect } from 'react';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then((res) => res.json())
.then((result) => setData(result));
}, []);
if (!data) return <div>Loading...</div>;
return <div>{data.message}</div>;
}
export default App;
データ取得はクライアント側で行われます。
Next.jsのレンダリングの特徴
Next.jsはReactを拡張しており、Server Side Rendering (SSR) や Static Generation(SG)、Incremental Static Regeneration (ISR) といった機能を標準で提供します。さらに、ReactのCSRもそのまま利用可能です。Next.jsは状況に応じて柔軟にレンダリング方式を選べます。
Server Side Rendering(SSR)
SSRでは、リクエストごとにサーバー側でJavaScriptを実行してHTMLをレンダリングし、クライアントに送信します。
CSRではブラウザ側でレンダリングしていましたが、SSRではブラウザは返ってきたHTMLを表示するのみとなります。
そのため、初回読み込み時にも高速で画面表示されるようになります。
また、レンダリングが完了したHTMLが返ってくるので、CSRと比較してSEOで有利です。
デメリットとしては、 動的データや大規模サイトではレスポンスに時間がかかる点です。
Next.jsコード例(SSR)
function Page({ post }) {
return <h1>{post.title}</h1>;
}
export async function getServerSideProps() {
const res = await fetch('https://api.example.com/post');
const post = await res.json();
return { props: { post } };
}
export default Page;
リクエストごとにサーバーでデータを取得。データ取得にはgetServerSidePropsを使用します。
Static Generation(SG)
SGでは ビルド時にHTMLを生成し、静的ページとしてサーバーに保管します。そしてリクエストがあれば静的ページを提供します。
これによりサーバーはHTMLを返すだけ、ブラウザは返されたHTMLを表示するだけ。となります。
そのため画面表示までの時間は非常に高速です。
デメリットとしては、ビルド時にコンテンツが確定するため、リアルタイムで変化するデータ(例: 株価)などを反映するのは難しいです。(いちいち手動でビルドする必要がある)
Next.jsコード例(SG)
function Page({ data }) {
return <div>{data.message}</div>;
}
export async function getStaticProps() {
const res = await fetch('https://example.com/api/data');
const data = await res.json();
return {
props: { data }, // ビルド時にデータが埋め込まれる
};
}
export default Page;
ビルド時にデータが取得され、静的なHTMLとして出力される。
データ取得にはgetStaticPropsを使用します。
Incremental Static Regeneration(ISR)
ISRは SG と SSRを組み合わせたものです。具体的には、ビルド時に静的ページを生成しつつ、指定した間隔(revalidate)で次のリクエスト時に内容を更新できる仕組みです。
ブログやニュース記事のような、「コンテンツは定期的に更新したいけどリアルタイムじゃなくてもいい」といった場合に最適です。
SGぐらいの高速さで、更新がある場合にも自動ビルドで画面に反映することができる点が魅力です。
デメリットとしては、リアルタイム性はあまりないので、どの場面でも使用できるというわけではない点です。
Next.jsコード例(ISR)
function Page({ post }) {
return <h1>{post.title}</h1>;
}
export async function getStaticProps() {
const res = await fetch('https://api.example.com/post');
const post = await res.json();
return {
props: { post },
revalidate: 60, // 60秒後に再生成
};
}
export default Page;
revalidate: 60で、60秒後、次のリクエストが来たタイミングで再生成が走る
まとめ
様々なレンダリング方法を見てきましたが、
- React: CSRに依存するため、SEOや初回ロード速度に課題が残る。
- Next.js: サーバーサイドの力を借りて、CSRの弱点を補いつつ、状況に応じた最適化が可能。
といった点が冒頭で言ったNext.jsの強みにもなります。