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;
}
}
}
現状では大きな問題は発生していないように見える。