Next.jsをSPAとして動作させる

基本的にNext.jsはReactのアプリケーションをSSR,SSG等の仕組みを使ってデプロイを行う。 公式サイトにもDockerを利用したデプロイ方法が紹介されているが、 yarn start でNode.jsのサーバを立ち上げている。

https://nextjs.org/docs/deployment

StaticなHTMLサイトの出力もサポートされていないわけではないが、Vercelにデプロイしないと使い物にならない。 例えば src/pages/todo/[id].tsx ファイルを作成した際には、 out/todo/[id].html ファイル等が生成される。 これをNginx等でホストするのは非常に難しい。 404フォールバック等を行う仕組みもデフォルトで提供されておらず、デプロイ先が固定化されてしまう。

https://nextjs.org/docs/advanced-features/static-html-export

Static HTML export with Nginx + Next.js

ネット上の文献を探すといくつか方法が出てくるが、Next.jsの内部APIを利用する方法・動的パスを扱えない方法などが紹介されていたので新しい方法を考えた。

まずNext.jsの設定を記述し、パスの形式を変更する。 デフォルト挙動では src/pages/about/index.tsx ファイルを作成すると out/about.html ファイルが出力されるが、この設定により out/about/index.html が作成されるようになる。

// next.config.js

module.exports = {
  trailingSlash: true, // 追記
}

そして404ページに以下の内容を記載する。 Next.jsのRouterが認識するパスを元に1度リダイレクトを行うというコードを記述している。

// src/pages/404.tsx
import Error from "next/error";
import { useRouter } from "next/router";
import React, { useEffect, useRef } from "react";

export default function NotFoundPage(): React.ReactElement {
  const first = useRef<boolean>(true);
  const router = useRouter();
  useEffect(() => {
    if (first.current) {
      router.replace(router.asPath);
      first.current = false;
    }
  }, [router]);

  return <Error statusCode={404} />;
}

そして最後に適当にnginxの設定ファイルを記述する。 try_filesの最後に先程記述した /404.html を配置している。

// nginx.conf

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server_tokens off;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
            try_files $uri $uri/ /404.html;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
}

現状では大きな問題は発生していないように見える。

続きを読む