Next.js
Overview
Reactをベースにしたフレームワークで、フロントエンド開発を効率化するための機能を提供しているフレームワーク。
Next.jsでCSR・SSR・RSCの扱い
SPAで軽視されがちな部分
Next.js API RouteとgetServerSideでCookieを参照するには
Reactとの違い
ブラウザは受信したJSファイルを処理することでh1タグとその内容を描写していることがわかる ブラウザ ページソースを確認すればわかる
Client Rendering 検証でソースコードを見ると、h1タグなどは出現しない。 JSをブラウザが処理している
Server-side Rendering 検証でソースコードを見ると、h1タグなどがある。 JSをNextがpre-Renderingをおこなっているため
Next強み
Nuxtだと、SSRにした場合はすべてのページがSSRとなってしまうが
Nextだと、このページはCSR、次はSSRなど分けることができる。もちろんSSGも
Next.jsの大きな特徴として、ひとつのプロジェクトの中で、SSGとSSRを混在して利用することができる
API Routeでcookieを設定する方法
Next JS Client と Express Server によるセッション Cookie の処理
Next.jsのdefault cache
各コマンド仕組み
$ npx next -h
で各コマンドの詳細を確認できる
$ next dev
ローカルでアプリケーションを起動します。
getStaticProps
(SSGで利用するmethod)を利用した場合でもSSR動作になる。
このコマンドでは、ホットリロードやエラーレポートなどの開発モードでアプリケーションを起動できる
ただし、create-next-appでスキャフォールディングしたプロジェクトに用意されているdevコマンドで起動したアプリはサーバーサイドレンダリング(以下SSR)が有効になっており、静的HTMLのみの確認ができない
そこでNext.jsで静的HTMLエクスポートしたアプリをローカルで確認する方法を調べました。 参考URL
$ next build
.nextフォルダーにプロダクション用のコードを吐き出す
本番用に最適化されたビルドを行い、各ルートの情報がコンソールに出力されます。
$ next start
このコマンドは next build
でビルドした後に実行すると、本番用としてサーバが立ち上がる。
プロダクション環境でアプリケーションを実行する
envはproduction
$ next export
outディレクトリに静的HTMLをエクスポートする。
サーバーにNode.jsを必要とせずにクライアントのみで実行できる静的HTMLを出力する。
localで確認する場合は
$ yarn add -D serve
というパッケージをインストールする
※静的ファイルをホスティングするローカルサーバ
各メソッド
ついでにuseSWRを利用してデ ータを取得してみます。 SWRはRenderingの種類ではない。Stale-While-Revalidateというキャッシュ戦略の略。
SWRとは
Vercelが開発する、HTTP RFC 5861で提唱された、SWRというキャッシュ無効化戦略に基づくライブラリ。 簡単に言うと、最初は普通にデータを取得してキャッシュとしてセット、次に参照された時にいったんキャッシュを返し裏でまたフェッチして、フェッチが完了したらキャッシュを最新のものに置き換えるというキャッシュ戦略をよしなにやってくれる。
Next.jsにimport React from 'react'はいるのか?
参考URL
結論いらない。
pages/apiとは(API Route)
next.jsでは pages/api
ディレクトリ以下にTypeScript (JavaScript) コードを配置するだけで、クライアントサイドJavaScriptから呼び出せるAPIを定義できる。
※pages/api
ディレクトリ以下の実装内容がクライアントに見られてしまうことはない。
- サーバーレス関数として配置される
注意
サーバーからデータを取得したい場合にAPI ルートにアクセスしてから、その API ルートを呼び出したいと思うかもしれませんgetServerSideProps。getServerSidePropsこれは不要で非効率的な方法です。サーバー上で と API ルートの両方が実行されているために、余分なリクエストが行われることになるからです。
とあるように getServerSideProps
からAPI Routeへアクセスするのは冗長(同じNode.jsプロセス内のため)
middleware
ミドルウェアは、一連のページのロジックを共有するあらゆるものに使用できる そこで、Next.js 12からは、ミドルウェアとしてエッジ関数(AWSのLambda@Edge的なもの?→中身はCloudflare Workersらしい)が導入されました。
エッジ関数は、リクエストが完了するまえにコードが実行できる。 クライアントとオリジンサーバーの間にエッジサーバーをおき、エッジ関数としてデプロイ。 エッジ関数は、認証、ボット保護、リダイレクト処理、サポートされていないブラウザ、機能フラグ、A/Bテスト、サーバー側の分析、ロギングなどあらゆるものに使用できる。 使い方は簡単で、 _middleware.tsを配置し、そのファイルに処理を書くだけです。
つまり、 VercelにReact Server Components (Next.js 12版)をデプロイするなら、それはミドルウェア上で(エッジ関数として)動作する、サーバーレスとして動くということらしいです。
/pages/_middleware.js(ts)ファイルが作成されている場合、/pagesディレクトリ以下すべてのページ(route)で実行される。
Next.jsでv12~ middlewareという機能が使えるようになった。 middlewareに書いた処理はリクエストが完了する前に実行される。 Cookieの値に応じてルーティングを振り分けたり、Basic認証を導入したりなど幅広い用途で使えそう。
Tips Vercelでホスティングをすると相性が良い。 VercelとNext.jsの組み合わせが強いのは、VercelにNext.jsをデプロイするとこのmiddleware部分をEdge Functionsで捌いてくれるという点です。つまり、静的なページに対するリクエストに対して、オリジンサーバーに触れことなくmiddlewareを実行できるということです。
_middleware.jsファイルが複数のディレクトリに配置されている場合は、階層が浅い方から順に実行されていく。
_document.js(tsx)によるカスタマイズ
Next.jsのPageコンポーネントはデフォルトでは <html> & <body>
タグの定義を行うが、それらを拡張したい場合は_document.js(tsx) を作成し、その中でDocumentコンポーネントを継承したクラスを実装する。
注意点
- SSR(サーバサイドレンダリング)のみの実行
next/image
next/image
が自身で持っている画像サーバが処理をしてくれるようになる。
仕組みとして、next/image
画像配信用のエンドポイントを立ててそこから配信される。
エンドポイントとしてのURLは以下となる。
https://igsr5.dev/_next/image?url=OOOO
このURLの中にある _next/image
がデフォルトで持つ画像配信用のエンドポイント。
ンドポイントがリクエスト毎に画像加工やキャッシュなどを行っています。反対にビルド時には画像の加工は行われておらず全てオンデマンドで行われている。
気をつけポイントとしてVercel以外でNext.jsをデプロイするときに _next/imageもアクセス可能な状態にしておくことが挙げられます。(_next/ 配下は他にもNext.js的に大事なエンドポイントが詰まっているのでミスらないためには _next/* で公開してしまうのもあり)
- レイアウトシフトが起きない
- サーバサイドでの画像リサイズ
- 適切な画像サイズの算出
- Lazy Loadが有効(特徴としてはNative Lazy LoadingではなくJS Lazy LoadingのためSafariなどのブラウザでも有効である。)
注意点 next/imageでは必ずしも指定したサイズの画像が返ってくるとは限らない。 next/imageでは画像の表示領域やユーザのディスプレイ解像度に合わせて適切な画像サイズを返す。
next/imageを仕事で使う際に気をつけたい仕様
Tips
かなりのTipsが散りばめられている nextの仕組みを読み解く
外 部ライブラリの利用
ときおり普通のReactで動くライブラリがNext.jsでビルドすると動かなかったりします。 こうした場合は、動的インポート(Dynamic Import)という機能で対処できる場合があります。動的インポートしたコンポーネントはクライアントサイドでレンダリングされるため、実質的にReactと同じように処理されるためです。
styled-components
Next.js(12): SWCには自動で組み込まれている Nextリファレンス(12) styled-components リファレンス
CSSの記述はSassと同じネストによる記述が可能
CSS in JSを使う意味の主なものとしては、 メンテナンス性の向上と、パフォーマンスの向上 JavaScriptフレームワークではコンポーネント単位でソースを管理することが一般的。 CSSを別管理でひとまとめにするよりもコンポーネントとセットで管理したほうがCSSの記述箇所を見つけやすくメンテナンス性が高くなる。
またCSS in JSを使うと、表示中の要素だけCSSを書き出し不要なCSSを書き出さな いという処理が可能になるためパフォーマンス性が上がる。 またSEOの評価も上がる。
ThemeProviderの利用 styled-componentsにはThemeProviderというAPIがあります。これはContext APIを使って、子のコンポーネントに、propsでスタイルを渡すことができます。 これで、スタイルを共通化できる。 ThemeProviderは、_app.jsで使用する。
next.js SSRでstyleを当てる
Next.jsとstyled-componentsが実行される前提とする環境が異なります。(styled-componentは元々クライアント側で動くことを前提としています)そのため、サーバーサイドでもstyled-componentsが働くようにする必要がある。
上記を対応するために、Next.js 12以前はBabel用styled-componentsのライブラリをダウンロードしなければいけず、めんどくさかった。 参考URL
next/dynamic
dynamic import(動的インポート)とは動的にimportを実行するための機能 ES2020でJSの仕様として導入された。dynamic importを利用すると非同期でモジュールを読み込む。
たとえば初期表示で読み込み不要なモジュールにdynamic importを適用すると初期ロードの負荷を軽減でき、表示速度を改善できます。
Next.jsにおけるdynamic importのつかいどころは主に『SSR回避』と『ロード時のパフォーマンス改善』の2点
リフェレンス 参考URL default exportとnamed exportでdynamic importする
next locale
next error
-
pages/_error.tsx
を作ると、SSR時やCSR時、例外が起きるなどした時やルーティング存在しないエラーが発生した時にそのページを表示してくれる。 ※このページで400エラー、404エラー、500エラーをハンドリングして、自前のページを作成すれば良い。 -
pages/_error.tsx
はproduction環境時(next build -> next start)にしか使われないので注意。 ※デバッグするときはnext buildをする必要がある -
next/errorのgetInitialPropsではCSR時に例外が起きた時、err.statusCodeに何も入っていないという問題がある
-
ビルトインのエラーページを表示させたい場合は
Error
コンポーネントをインポートする。
import React from 'react';
import { NextPage, NextPageContext } from 'next';
// production時(next buildの成果物を使っている時)のエラー表示に使われる
// See Also: https://nextjs.org/docs/advanced-features/custom-error-page
interface Props {
statusCode: number;
}
const Error: NextPage<Props> = ({ statusCode }) => {
// ここでエラーページをちゃんと構築する。statusCodeが400の時BadRequest、
// 404/405の時Not Found、500の問Internal Server Errorが出るように正しく処理すれば良いだろう
return <div>{statusCode}エラーが発生しました</div>;
};
Error.getInitialProps = async ({ res, err }: NextPageContext) => {
// statusCodeを算出する。
// - resが存在する時はSSRであり、res.statusCodeをそのまま利用すれば良い。
// - resがない場合はCSRである。
// - err.statusCodeがあればそれをそのまま利用する
// - 意図しない例外が起きてerrがここに渡ってくる場合、単なるErrorオブジェクトが入っていてstatusCodeプロパティがない。errがある時点でISEなので500にする
// See Also: https://nextjs.org/docs/advanced-features/custom-error-page
const statusCode = res ? res.statusCode : err ? err.statusCode ?? 500 : 404;
return { statusCode };
};
export default Error;
カスタムエラーページ
参考URL デフォルト挙動 プライベートでやれば綺麗にできそう
page/404.tsxを作成せずに、page/ _error.tsxを設定すると下記の警告が表示される。 なお、存在しないURLにアクセスするとpage/_error.tsxの内容が表示されている。
優先順位 pages/404.tsx or pages/500.tsx ↓ pages/_error.tsx ここにif文で条件分岐してもいいが公式のハンドリングを使用した方がいい。
pages/404.jsが"設置されていなければ"pages/_error.js"、"next/error"の優先順位
404ページ 頻繁にアクセスされる可能性を考慮し、NextJSではデフォルトでビルド時に静的に生成される。 ※getStaticPropsビルド時にデータをフェッチする必要がある場合は、このページ内で使用できる。
500ページ 頻繁にアクセスされる可能性を考慮し、NextJSではデフォルトでビルド時に静的に生成される。 ※getStaticPropsビルド時にデータをフェッチする必要がある場合は、このページ内で使用できる。
pages/_error.tsx
pages/_error.jsを設定した場合の挙動
getServerSidePropsで {notFound: true}
を返した場合、_error.jsが表示される (pages/404.jsがない場合)
getServerSidePropsでErrorをthrowした場合、_error.jsが表示される
下記のようにstatusCodeを指定した場合、デフォルトのエラーページが表示される。
-> pages/_error.jsを定義したからといって、 next/errorが変更される訳ではない
import Error from 'next/error'
export default function Test() {
return (
<Error statusCode={500} />
)
}
pages/500.jsを設定した場合の挙動 -> getServerSidePropsでErrorをthrowした場合、デフォルトのエラーページが表示される
import NextErrorComponent from 'next/error'について
-
メッセージ表示は一部のみ HTTP 400 / 404 / 405 / 500以外のステータスコードを投げ込むと、「An unexpected error has occurred」扱いされる。 ※他のメッセージを使用したい場合は
titleプロパティ
を使う。 -
HTTP Status Code SSGではerrorを出してもHTTP上は200が返る。
Next error ハンドリング
next env
.env.local
$ next dev
のときに読み込まれる。
.env.development
NODE_ENVがdevelopmentのとき読み込まれる。
.env.production
NODE_ENVがproductionのときに読み込まれる。
next サーバーレスモード
参考URL Next.js8からサーバレスモードが実装された。 従来であればひとつのサ ーバ上に乗せて動作させるものを、AWS Lambdaのような機能ごとに分割して動作させることができる。 ただ、Next.jsとしては分割するだけにとどまる
# next buildした結果
frontend/.next
├── build-manifest.json
├── cache
├── package.json
├── react-loadable-manifest.json
├── server # これがserver側で動作するやつ。pages/* ディレクトリ配下
├── static
└── trace
Serverless Componentsでのdeployした際の処理フロー
Tips
SWR
とても参考になる
参考URL
SWRを使おうぜって話(導入についてわかりやすい)
Next.jsがデフォルトで使うSWCは、SWCのラッパーになっていて、SWCで使える機能が一部制限されていたり、拡張されていたりします。このデフォルトで使われるSWCのことをNext-SWCという(公式ではNext.js Compilerとも呼ばれている)
データ取得専用のReact Hooksライブラリ(あくまでGETに使う)
※POSTなどには使用できるがおすすめはしない
Next.jsと同じチームによって作成されている、データ取得のためのReact Hooksライブラリ
仕組み
“SWR” という名前は、 HTTP RFC 5861 で提唱された HTTP キャッシュ無効化戦略である stale-while-revalidate に由来しています。 SWR は、まずキャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという戦略です。
この考え方の仕組みにより、データが高速に返却されさらに自動で再フェッチ(revalidate)されるようになっている。
メリット
SWRのメリットは以下
- fetchを使用したクライアントサイドのデータ取得
- データ取得状態の管理
- エラー処理
- データキャッシュ