🦔

NextJSでSSR/SSGの挙動を確認する。

2021/08/28に公開

https://qiita.com/G-awa/items/639f4f83aa4d97bc1f0d

こちらのサンプルプロジェクトを利用。

serveパッケージで静的ファイルをホスティングするローカルサーバーを立ち上げる。

yarn add -D serve

export, serveコマンドを追加

  "scripts": {
   "dev": "next dev",
   "build": "next build",
   "start": "next start"
   "export": "next build && next export", 
   "serve": "yarn export && serve ./out"
  },

next build.nextフォルダにプロダクション用のコードを吐き出す。

next build builds the production application in the .next folder. After building, next start starts a Node.js server that supports hybrid pages, serving both statically generated and server-side rendered pages.

https://nextjs.org/docs/deployment#nodejs-server

next exportは、静的ファイルを出力するコマンドで、ルートは以下にoutディレクトリを生成する。

next export allows you to export your app to static HTML, which can be run standalone without the need of a Node.js server.

The exported app supports almost every feature of Next.js, including dynamic routes, prefetching, preloading and dynamic imports.

next export works by prerendering all pages to HTML. For dynamic routes, your page can export a getStaticPaths function to let the exporter know which HTML pages to generate for that route.

https://nextjs.org/docs/advanced-features/static-html-export

yarn serveを実行すると

  • next build
  • next export
  • serve ./out

が実行される。

next exportはいつ使うか?

  • landing pages
  • blogs
  • news articles

などのページに使える。

When to use next export?
next export is recommended if you have some dynamic pages which need to some data to be fetched only at 'build' time. It is perfect for pages like landing pages, blogs, news articles etc, or for other kinds of pages which are updated only during code builds. You can setup a background task to build your code at regular intervals if your page data needs to be updated more frequently. This will speed up your 'first paint' speed and also provide the entire page data to search engine crawlers for indexing.

https://stackoverflow.com/questions/61724368/what-is-the-difference-between-next-export-and-next-build-in-next-js

SSGを行う

  • pages/index.jsgetStaticProps関数を追加
  • pages/shows/[id].jsgetStaticProps, getStaticPaths関数を追加。

getStaticPathsは、

getStaticPathsはpathsとfallbackが必須パラメーターです。
pathsは前述通り事前にビルドするパス対象を指定するためのもです。
fallbackは事前ビルドしたパス以外にアクセスしたときの動作を決めるものでfalse の場合404 pageとなる。

pages/index.js
import Link from "next/link";
import fetch from "isomorphic-unfetch";

const Index = (props) => (
  <div>
    <h1>Batman TV Shows</h1>
    <ul>
      {props.shows.map((show) => (
        <li key={show.id}>
          <Link href="/shows/[id]" as={`/shows/${show.id}`}>
            <a>{show.name}</a>
          </Link>
        </li>
      ))}
    </ul>
    <div>ビルド時間: {props.buildtime}</div>
    <div>{props.test}</div>
  </div>
);

export async function getStaticProps() {
  console.log(`getStaticProps`);
  const res = await fetch("https://api.tvmaze.com/search/shows?q=batman");
  const data = await res.json();
  console.log(`Show data fetched. Count: ${data.length}`);
  const buildtime = new Date().toString();
  return {
    props: {
      test: "testです",
      shows: data.map((entry) => entry.show),
      buildtime,
    },
  };
}

export default Index;
[id].js
import fetch from "isomorphic-unfetch";

const Post = (props) => (
  <div>
    <h1>{props.show.name}</h1>
    <p>{props.test}</p>
    <p>{props.buildtime}</p>
    <p>{props.show.summary}</p>
    {props.show.image ? <img src={props.show.image.medium} /> : null}
  </div>
);

export async function getStaticProps(context) {
  console.log(`個別ページ getStaticProps`);
  console.log(context);
  const id = context.params.id;
  console.log(`id: ${id}`);

  const res = await fetch(`https://api.tvmaze.com/shows/${id}`);
  const show = await res.json();
  console.log(show);
  const buildtime = new Date().toString();
  return {
    props: {
      test: "個別ページ getStaticPropsです",
      show,
      buildtime,
    },
  };
}

export async function getStaticPaths() {
  const res = await fetch("https://api.tvmaze.com/search/shows?q=batman");
  const data = await res.json();

  const paths = data.map((d) => `/shows/${d.show.id}`);
  return { paths, fallback: false };
}

export default Post;

yarn serveを実行する。

事前に10個の静的なファイルが生成されたことがわかる。

buildのタイミングでconsole.log()は削除されている。

yarn devconsole.log()の出力は、ブラウザのコンソールでは確認できないが、Terminalの方から確認できる。

参考

next exportが導入された理由

バットマンのデモサイトrepository

case-study-ssr-react

Discussion