[Next.js] SSRを無効にする方法

概要

Nuxt.jsはデフォルトでサーバサイドレンダリングが有効になっているため、サーバサイドでは存在しないwindow, localStorage, sessionStorageなどのオブジェクトを参照しようとするとエラーになってしまう。

Nuxt.jsの場合はnuxt.config.tsでssr: falseを指定することでSSRを無効にすることができるが、Next.jsの場合はnext/dynamicを使ってコンポーネントを動的にインポートする必要がある。

エラーの例

const snapshotsJson = localStorage.getItem('hoge');
ReferenceError: localStorage is not definedとなる。

また、cookie, localStorage, sessionStorageなどブラウザで保持している値をstateに代入すると、サーバサイドとブラウザでのレンダリング結果に差分が発生してしまうため、以下のようなエラーとなることがある。
Unhandled Runtime Error
Error: Text content does not match server-rendered HTML.
Warning: Text content did not match. Server: “” Client: “0”
See more info here: https://nextjs.org/docs/messages/react-hydration-error

解決方法

特定の場所のみエラーを回避するのであれば、以下のように書くことができる。

if (typeof localStorage !== "undefined") {
  console.log(localStorage.getItem('hoge'))
}

Next.jsアプリ全体やコンポーネント単位でエラーを回避する場合は、next/dynamicを使ってコンポーネントを動的にインポートする必要がある。
next/dynamicはオプションでssr: falseを指定するとSSRは無効となりSPA(CSR)として動作する。

_app.jsx(_app.tsx)にて、ssr: falseでインポートしたコンポーネントで全体を囲むとNext.jsアプリ全体でSSRが無効となる。

import type { AppProps } from 'next/app'
import dynamic from 'next/dynamic';

const Wrapper = dynamic(() => import('./Wrapper'), { ssr: false });
export default function App({ Component, pageProps }: AppProps) {
  return (
    <Wrapper>
      <Component {...pageProps} />
    <Wrapper>
  );
}
import { FC, ReactNode } from 'react';

type WrapperProps = {
  children?: ReactNode;
};
const Wrapper: FC<WrapperProps> = ({ children }) => {
  return <div className="wrapper">{children}</div>;
};

export default Wrapper;

参考サイト

Attention Required! | Cloudflare

コメント

タイトルとURLをコピーしました