Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

サブディレクトリでNext.jsのアプリをデプロイしたい!!

結構こういう要求はあるとおもいます。

解決する課題

  • /staticへのリンクが途切れる
  • <Link>で遷移するとbasepathが変わる

つまり、サブディレクトリ以下でNext.jsを使ったSPAをしたい!!という人向けの記事です。

/staticへのリンクをサブディレクトリ以下になるようにする

たとえばexample.com/next-appでデプロイしたいとき、example.com/next-app/_next/static以下にJSファイルなどは置かれます。しかし、なにも設定しないままだとNext.jsではexample.com/_next/staticへのリンクを張るため404となってしまいます。

これを解決するには、next.config.jsでassetPrefixを設定する必要があります。

const isProd = process.env.NODE_ENV == 'production';

const url = isProd ? 'https://example.com/next-app' : '';
module.exports = {
    assetPrefix: url,
}

これでローカルでも本番環境でも/staticへアクセスできるようになります。

<Link>で遷移するとbasepathが変わる

上の方法で/staticへアクセスできるようになりました。しかし、実はルーティングをしている場合これだけでは対応が不十分です。

たとえば以下のような<Nav>を考えます。

import * as React from 'react';
import Link from 'next/link';

const Nav = () => (
    <nav>
        <ul>
            <li><Link href="/"><a>Top</a></Link></li>
            <li><Link href="/about"><a>About</a></Link></li>
            <li><Link href="/content"><a>Content</a></Link></li>
        </ul>
    </nav>
);

このNav要素はローカル環境ではなんの問題もなく動作します。しかし、本番環境ではうまく動作してくれません。たとえば本番環境でAboutをクリックすると、example.com/aboutへとURLが変わります。もうおわかりですね。この状態でリロードするとページが読み込まれません。

この問題の解消方法はとても簡単です。as属性をつけてあげるだけです。

<Link href="/about" as="/next-app/about"><a>About</a></Link>

しかし、今度はローカルでうまく動作しません。困りましたね。

設定で切り替える

参考: Deploy your NextJS Application on a different base path (i.e. not root)

どうやらNext.jsにはnext.config.jsから値を取ってくる機能があるようです。

import getConfig from 'next/config';

const {publicRuntimeConfig} = getConfig();

こうするとnext.config.jsで設定したpublicRuntimeConfigの値を取ってこられるようになります。あとはこれを設定して、Linkのasでこれを使った設定をしてやれば完成です。詳しいコードはこちらを参考にしてください。

参考