Next.js 9ではDynamic Routingが標準でサポートされ使用感が大きく改善されました。
このDynamic Routingで構築したアプリをexportした場合に一手間必要だったので考慮したことをまとめておきます。
この構成でデプロイを行う際には、ビルド時にデータを全部仕込むか、クライアント側で(APIを叩くなどして)データを仕込むかで大きく対処方法が変わります。
今回の想定アプリ
次のようなページを持つアプリケーションを想定します。
/
/about
/show/[id]
1.ビルド時にデータを仕込む方法
exportする際には、next.config.js
のexportPathMap
を利用し、出力するファイルの調整を行っていきます。
exportPathMapで、キーにpath、バリューにpage(pageコンポーネントの位置)、query(クエリパラメータ)などの情報をもたせたオブジェクトをそれぞれ作り返り値とします。コードを見たほうが早いでしょう。
const fetch = require('isomorphic-unfetch');
module.exports = {
exportPathMap: async function() {
const paths = {
'/': { page: '/' },
'/about': { page: '/about' }
};
const res = await fetch('https://api.tvmaze.com/search/shows?q=batman');
const data = await res.json();
const shows = data.map(entry => entry.show);
shows.forEach(show => {
paths[`/show/${show.id}`] = { page: '/show/[id]', query: { id: show.id } };
});
return paths;
}
};
https://nextjs.org/learn/excel/static-html-export/exporting-other-pages より
この際、showのデータを参照するためにAPIを叩いて、結果からexportPathMapのデータを生成します。
2. クライアント側でデータを読み込む場合
ビルド後にもデータが増えることが想定されている場合、ビルド時にexportPathMapを使わない選択肢もあります。
exportPathMapを設定しない場合は、次のようなファイルが生成されます。
/index.html
/about/index.html
/show/[id]/index.html
問題は/show/[id]/index.html
です。ただ、NetlifyやFirebase Hostingにデプロイするだけでは、example.com/show/[id]
でしか開くことができません。
そこで各プラットフォームに、example.com/show/1
などのURLを叩いた時に、/show/[id]/index.html
の内容を返すリライトの設定を行います。
例えばNetlifyでは、公開ディレクトリに次のような_redirects
を用意します。
/show/:id /show/[id] 200
同じくFirebase hostingではfirebase.jsonにリライトの設定を追加します。
こういった設定を加えることで、データが増えた場合でも404を返さずにコンテンツを表示できます。
ただ、この対応だけでは動的にogpを返却することや、速度的なデメリット(1の方法ではHTML読み込み時点でコンテンツが表示されている)を背負うことになります。
特に2.の方法は今後SSRを使いたいけど、今はSSRを行わず静的ファイルとして返す暫定対応的な使い方になると思います。
覚えて置くと初期フェーズからNext.jsの採用を行え、将来SSRをする際に移行コストが小さくなるのでおすすめです。