Next.jsでは、ビルド&エクスポートで生成した静的サイトを、FTPなどでドメインのルートディレクトリではなく、サブディレクトリにデプロイすると、様々なパスがずれて表示が崩れてしまいます。
https://ドメイン名/〇〇/
のような階層に Next.js をデプロイするための設定方法をまとめます。
- basePathの設定
- assetPrefixの設定
- publicRuntimeConfigを使って、画像やリンクのパスを設定
basePath の設定
next.config.js
の中にサブディレクトリの設定を追記していきます。
開発環境ではルートディレクトリ、本番環境ではサブディレクトリ配下というように、環境によって分岐できるように設定していきます。
/* 公開時のサブディレクトリ */
const SUB_DIRECTORY = "/sub_directory";
/* 本番環境と開発環境の分岐用のフラグ */
const isProd = process.env.NODE_ENV == "production"
module.exports = {
// 本番環境では SUB_DIRECTORY それ以外は空欄
basePath: isProd ? SUB_DIRECTORY : "",
}
これでアプリ全体のパスプレフィックスを設定することができますが、これだけではCSSやJSなどのアセットファイルのパスがずれたままです。
assetPrefix の設定
アセットファイルのパスを修正するために、next.config.js
の module.exports
内に assetPrefix
を設定していきます。
module.exports = {
// 本番環境では SUB_DIRECTORY それ以外は空欄
assetPrefix: isProd ? SUB_DIRECTORY : "",
}
これでJSやCSSのパスが正常に読み込まれます。
publicRuntimeConfigを使って、画像やリンクのパスを設定
コンポーネント内の img
タグや Link
タグで設定したパスも、設定ファイルをもとに開発環境と本番環境でルートパスの出し分けができるように改修していきます。
Reactコンポーネント内で next.config.js
の設定値を呼び出せるように、まずは publicRuntimeConfig
を設定します。
module.exports = {
publicRuntimeConfig: {
basePath: isProd ? SUB_DIRECTORY : "",
}
}
これで、コンポーネント側から publicRuntimeConfig.basePath
を参照できるようになります。
import getConfig from "next/config";
import Link from "next/link";
const { publicRuntimeConfig } = getConfig();
export const SomeComponent = () => {
// jsxで設定する各パスの前にこの basePath を入れる
const basePath = (publicRuntimeConfig && publicRuntimeConfig.basePath) || "";
return (
<div>
<img src={`${basePath}/vercel.svg`} alt="Vercel Logo" />
<Link href="/about" as={`${basePath}/about`}>
<a>リンク</a>
</Link>
</div>
);
}
Linkタグの場合は、動的ルーティングの as
を使用します。
静的エクスポートをするので next/image
の Imageタグは使用できません。
以上の設定で、開発環境と本番環境でアプリのディレクトリを出し分けすることができるようになりました。
確認として、開発時は next dev
で localhost:3000
で、
本番環境のローカルでの確認は、next build && next export
で書き出したあとに、 next start
で localhost:3000/サブディレクトリ名
で確認することができます。
/* 公開時のサブディレクトリ */
const SUB_DIRECTORY = "/sub_directory";
/* 本番環境と開発環境の分岐用のフラグ */
const isProd = process.env.NODE_ENV == "production"
module.exports = {
basePath: isProd ? SUB_DIRECTORY : "",
assetPrefix: isProd ? SUB_DIRECTORY : "",
publicRuntimeConfig: {
basePath: isProd ? SUB_DIRECTORY : "",
},
// ...
}