NextjsでStatic Generationしてみる

Tatsuya Asami
7 min readJul 10, 2022

--

【概要】

  • Nextjsで作ったページをStatic GenerationしたのをVercelにデプロイ
  • コンテンツ、レイアウト、変数名、どこに何を書くかなどは全て適当
  • お店の情報を閲覧するページをイメージして作成
  • データベースとは繋がずにjsonから直接
  • Github↓
  • デプロイしたやつ↓

【完全に理解したこと】

  • create next-appで雛形作成
npx create-next-app@latest --typescript
  • pagesディレクトリ配下に作成したファイル名のurlにページが作成される。
  • サーバーのコードは pages/api ディレクトリ配下に置く。エンドポイント名はファイル名と同じになる。
  • お店データ
// data/shopsexport type Shop = Readonly<{
name: string;
rank: 1 | 2 | 3 | 4 | 5;
bringIn: boolean;
}>;
export const SHOPS: Shop[] = [
{ name: "俺の塩", rank: 3, bringIn: false },
{ name: "君の豚", rank: 2, bringIn: true },
{ name: "Your soy", rank: 4, bringIn: false },
{ name: "MyMiso", rank: 5, bringIn: false },
];
  • 動的ルーティングをする場合は getStaticPaths で存在するルートを抽出する必要がある。また、ファイル名は [] で囲み、ファイル名と同じオブジェクトを返す必要がある様子。そしてこの関数はクライアントでは実行されない。ビルドの際に実行される。
// [name].tsxtype Params = Pick<Shop, "name">;export const getStaticPaths: GetStaticPaths<Params> = () => {
const paths = SHOPS.map(({ name }) => ({ params: { name } }));
return {
paths,
fallback: false,
};
};

paths は下記のような配列を返している

[
{ params: { name: '俺の塩' } },
{ params: { name: '君の豚' } },
{ params: { name: 'Your soy' } },
{ params: { name: 'MyMiso' } }
]

fallbackはfalseにすると存在しないurlにアクセスすると404ページを返すようにする。trueにすると404にはならず、最初のリクエストでフォールバックのバージョンを提供するらしいがどういうことなのかはよくわからない。大量のページを生成する時に使うらしい。他にもblockingというのもある。

  • 今回は保存されてるデータはローカルにあるが、サーバーから取得するイメージでfetchして取得。 getStaticProps getStaticPaths からpages/api にアクセスするべきではなく、直接fetch するコードを書くべきらしい。今回は pages/api を外部サーバーに見立てて直接fetchしてしまった。
// getShopData.tsexport async function loadShops(): Promise<Shop[]> {
try {
const res = await fetch(`${process.env.ORIGIN}/api/shop`);
const data = await res.json();
return data;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
}
throw error;
}
}
export const getShopData = async (name: string): Promise<Shop> => {
const shops = await loadShops();
const shopName = shops.find((shop) => shop.name === name);
return shopName ?? { name: "不明なお店", rank: 1, bringIn: false };
};
  • コンポーネントでは取得した値を表示。nextにはLink, Image, Meta等便利なタグがある。
// [name].tsxconst Shop: React.FC<Props> = ({ shopParams }) => {
return (
<div className={styles.container}>
<main className={styles.main}>
<h1>{shopParams.name}</h1>
<p>星: {shopParams.rank}</p>
<p>持ち込み: {shopParams.bringIn ? "可" : "不可"}</p>
<Link href="/">
<a>戻る</a>
</Link>
</main>
</div>
);
};
  • 完成!ChromeのdevToolでcssを上書きした状態でページ遷移してもリセットされないので、HTMLが再読み込みされていないのも確認出来た。
  • github-pagesに載せようと思ったが手間がかかりそうだったのでvercelにデプロイ。環境変数の指定のみで簡単にページが出来て便利。githubにpushすると自動でデプロイが更新されるなどの連携も自動でやってくれた。便利で楽ちん。

【感想】

  • 環境構築をはじめとして、何かといい感じにやってくれるので便利そうな印象。
  • ページごとにSSG, SSR, SPA等も簡単に切り替えられるのでページごとの最適化などもしやすそう。
  • ドキュメントが充実していてよい。SEO関連のドキュメントも結構ボリュームあった。
  • ESLint, Prettier, huskyなどの設定や作成するコンテンツについこだわってしまいたい気持ちを捨てて試したいことを試せて大人になったなと思った。

--

--

Tatsuya Asami
Tatsuya Asami

Written by Tatsuya Asami

Front end engineer. React, TypeScript, Three.js

No responses yet