Next.jsにおけるレンダリング方法を解説
今回はNext.jsについて解説していきます。
フロントエンドエンジニアとして働くなら、Nextは必須技術となるのでぜひこれを機に学んでみましょう。
特に今回はレンダリングの方法に重点を置いて解説していきます。
CSR/SSR/SSG/ISR
まず、生成されるページの種類について解説していきます。
Nextには主に次の4種類があります。
- CSR
- SSR
- SSG
- ISR
それぞれ具体的に解説していきます。
CSR
CSRとはClient Side Renderingの略になります。
CSRではクライアントのリクエストに対して空のHTMLとJSを返し、クライアント側でJSを実行して画面を描画します。
要は、ユーザー側でページを生成する方式になります。
JavaScriptで画面を表示させることになるので、クローラーがページ内容を検出できなくなり、SEO的に問題があります。
(一応、クローラーがJavaScriptを実行できるようになってきているので、この問題は解決されつつあるみたいです。)
SSR
次に紹介するのが、SSRになります。
こちらはServer Side Renderingの略になります。
先ほど述べたように、CSRにはSEO上の問題があるため、SSRという手法を使うようになりました。
これはクライアントからのリクエストに対して、サーバー側でHTMLを生成する方法になります。
この方法では、先ほど述べたSEOの問題を解決することができます。
とはいえ、CSR・SSRは共にリクエスト後にページを生成するので、表示が遅くなります。
SSG
次に紹介するのが、SSGになります。
こちらはStatic Site Generationの略になります。
そして、先ほど述べたページの表示速度を改善するのが、このSSGになります。
こちらはビルド時にページを事前に生成しておく手法になります。
この方法はクライアントのリクエストに対してHTMLを返すだけで良いので、かなり高速になります。
けれどビルド時しかページを生成しないので、ページの更新性が悪くなります。
例えば、TwitterのようなアプリをSSGで作ると、ビルドするまで新しいツイートが表示されないという問題が発生します。
ISR
最後に紹介するのが、ISRになります。
こちらはIncremental Static Regenerationの略になります。
このISRを使用することで、先ほどの更新性の問題を解決するのがこのISRになります。
ISRは一定時間ごとに、サーバー側で再ビルドを自動で実行する方法になります。
こうすることで、頻繁にページを更新することができるので、さらに良い感じの画面を表示できるようになります。
Next.jsにおけるレンダリングの設定方法
次に、Next.jsにおける具体的なレンダリングの設定方法を解説していきます。
Next.jsにおいては、まず全てのページ分のHTMLが事前生成されます。
そして、CSRさせるコンテンツは、良しなにNext.jsが振り分けて別途CSRされます。
ちなみん、上記は何も設定しないページの場合です。
SSRやSSGを使う場合は、ページごとで設定をする必要があります。
次はそちらを具体的に解説していきます。
Next.jsにおけるSSR
Next.jsではSSRをするために、getServerSidePropsという関数を使います。
こちらはSSRを実行するための関数になります。
さらに具体的に説明すると、リクエスト時に呼び出されてデータを取得をし、それをpropsとして各ページに利用可能にするための非同期関数です。
実際に使い方は次の通りです。
const Bar = ({data}) => {
return(
<>
<div>hoge</div>
<div>{data[0].title}</div>
</>
)
}
export default Bar
export async function getServerSideProps() {
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a}
}
}
こうすることで、サーバー側で事前に生成したページをクライアントに返せるようになりました。
また、このgetServerSidePropsはcontextという引数を取ることができます。
このcontextを使うことで、Pathの情報などを取得をできます。
なのでcontextを使うことで、ダイナミックルーティングを実現させつつ、SSRをすることができます。
まず、pages配下に/posts/[id].jsxを作成します。
ファイルの内容は次の通りです。
const Bar = ({data,id}) => {
return(
<>
<div>hoge</div>
<div>{data[id].title}</div>
</>
)
}
export default Bar
export async function getServerSideProps(context) {
const {params:{id}} = context
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a,id}
}
}
こうすることで、例えば/posts/1や、/posts/2にアクセスした時に、それに合わせた記事の内容を表示することができます。
その他の設定
最後に、その他の設定をいくつか紹介します。
まずredirectを使うことで、ページをredirectさせることができます。
そして、オプションでpermanentの設定も可能です。
export async function getServerSideProps(context) {
const res = await fetch(`https://.../data`)
const data = await res.json()
if (!data) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: {}, // will be passed to the page component as props
}
}
次に、notFoundを紹介します。
こちらはデータが見つからなかった時などに404を表示させるものになります。
export async function getServerSideProps(context) {
const {params:{id}} = context
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
if (!a[id]) {
return {
notFound: true
};
}
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a,id}
}
}
ちなみに、SSRはnode.js上で実行されるので、コンポーネント内で普通にwindowオブジェクトなどを使っているとエラーになります。
なので、windowオブジェクトなどのブラウザ上でしか動かないものを使う場合は、useEffect内で使用するようにしましょう。
Next.jsにおけるSSG
次に、Next.jsにおけるSSGの方法について解説していきます。
NextでSSGを使いたい時は、SSRの時と同じようにgetStaticPropsという関数を使用します。
この関数を使うことで、SSGでページを生成することができます。
実際の使い方は次のとおりです。
const Bar = ({data}) => {
return(
<>
<div>hoge</div>
<div>{data[0].title}</div>
</>
)
}
export default Bar
export async function getStaticProps(context) {
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a}
}
}
ちなみにこのgetStaticPropsという関数は、開発時はリクエスト毎に実行され、本番はビルド時に実行されます。
getStaticPaths
また、getStaticPathsと一緒に使用することで、ダイナミックルーティングもさせることができます。
const Bar = ({data,id}) => {
return(
<>
<div>hoge</div>
<div>{data[id].title}</div>
</>
)
}
export default Bar
export async function getStaticPaths() {
return {
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
fallback: false,
}
}
export async function getStaticProps(context) {
const {params:{id}} = context
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a,id}
}
}
getStaticPathsを使うことで、事前生成させるページのパスを配列で渡すことができます。
またfallbackも使用可能で、trueの場合はpaths プロパティで指定したパラメーター以外でのアクセス時に、サーバーサイドで getStaticProps を呼び出して動的にページを生成します。
そして、falseの場合は404を返します。
またblockingというプロパティもあり、trueの場合はページ生成中に「フォールバックページ」を返しますが、blockingの場合は生成した後に初めてレスポンスを返します。
ちなみに、このfallbackの動きはサーバーにデプロイしてる状態でしか機能しないです。
Next.jsにおけるISR
最後に紹介するのが、ISRの方法になります。
この設定方法はかなり簡単で、getStaticProps の返り値にrevalidateプロパティを追加するだけです。
そして、設定した秒数ごとにサーバー側でページを再生成してくれます。
(厳密には指定した秒数後にユーザーがアクセスした時に、際ビルドが実行される。)
また、指定した秒数間は1度しか再ビルドが実行されないようになっているので、無駄な再生成も防ぐことができます。
実際のコードは次の通りです。
export async function getStaticProps(context) {
const {params:{id}} = context
// 外部からデータを取得する
const data = await fetch("https://qiita.com/api/v2/items")
const a= await data.json();
// propsプロパティの値はHomeコンポーネントのpropsに渡される
return {
props: {data:a,id},
revalidate: 10
}
}
ただ、このISRはVercelを使わないと設定がかなり大変と言われています。
なので、ISRを使いたい場合は大人しくVercelを使うことをおすすめします。
まとめ
今回は、Next.jsにおけるレンダリング方法について解説しました。
ぜひ、この記事を参考にしてNextの理解を深めてください!
宣伝
0からエンジニアになるためのノウハウをブログで発信しています。
また、YouTubeでの動画解説も始めました。
YouTubeのvideoIDが不正ですインスタの発信も細々とやっています。
興味がある方は、ぜひリンクをクリックして確認してみてください!
Discussion