Next.js 的 getStaticPaths

如果想要 Next.js 在 server 端就產出網頁內容,並且又想使用 dynamic routes 的話,除了使用 getStaticProps 之外,還必須搭配 getStaticPaths,如此一來 Next.js 才會預先在 server 端就把畫面渲染出來。

那麼,在什麼樣的情況下會需要使用 getStaticPaths 呢?部落格就是一個很好的例子,我們將文章寫好後,透過 getStaticPaths 產生出所有文章的 paths,接著在 getStaticProps 就可以根據 path 去 render 不同的頁面。Next.js也有列出一些應該使用 getStaticPaths 的情況,有興趣的讀者可以點擊連結去看看。

本篇文章不會介紹什麼是 Next.js,而會著重在如何使用 getStaticPaths,所以如果讀者不知道什麼是 Next.js 的話,推薦先去 Next.js 的 Learn Course 學習。

檔案結構

接下來會以部落格做為例子來講解,以下是專案的檔案結構:

  • pages
    • [post].tsx
    • index.tsx
  • posts
    • foo.md
    • bar.md
  • 其餘資料夾及檔案

[post].tsx

在[post].tsx 中除了要 export page component 之外,還需要 export getStaticPaths 以及 getStaticProps。

type Props = {
  metadata: PostMetadata;
  content: string;
};

type Query = {
  post: string;
};

export const getStaticPaths: GetStaticPaths<Query> = async () => {
  // ...
};

export const getStaticProps: GetStaticProps<Props, Query> = async ({ params }) => {
  // ...
};

const Post: NextPage<Props> = ({ metadata, content }) => {
  // ...
};

export default Post;

getStaticPaths

getStaticPaths 需要回傳一個 object,這個 object 需要包含 paths 和 fallback,其中 paths 是用來決定哪些 paths 會 pre-rendered,而 fallback 則是用來決定那些沒有 pre-rendered 的 path 要如何顯示。

export const getStaticPaths: GetStaticPaths<Query> = async () => {
  return {
    paths: [{ params: { post: 'foo' } }, { params: { post: 'bar' } }],
    fallback: false,
  };
};

由於 dynamic routes 的檔案名稱叫做[post].tsx,在 params 中就一定要有 post 這個 property,否則 dynamic routes 就會失效。至於 fallback 總共有三種值可以傳入,true, false 和 'blocking',這邊傳入 false 代表任何不是從 getStaticPaths 回傳的 paths 都會被導向 404 page,如果有讀者想更深入了解 fallback 的話,可以到這裡看看。

getStaticProps

接著我們就可以依據在 getStaticPaths 中獲得的 params 來回傳 page component 所需要的 Props。

export const getStaticProps: GetStaticProps<Props, Query> = async ({ params }) => {
  if (!params) return { notFound: true };

  const post = params.post;
  const { metadata, content } = getPostData(post);
  return {
    props: {
      metadata,
      content,
    },
  };
};

上面的 getPostData 會回傳 posts/foo.md 或是 posts/bar.md 中的 metadata 以及內容,由於本篇文章的主題是介紹 getStaticProps,所以就不多做贅述。

Post

最後就是 Post component 根據 getStaticProps 回傳的 props 來去渲染畫面。

const Post: NextPage<Props> = ({ metadata, content }) => {
  const { title, description } = metadata;
  return (
    <div>
      <Head>
        <title>{title}</title>
        <meta name="description" content={description} />
      </Head>

      <Markdown>{content}</Markdown>
    </div>
  );
};

結語

由於這篇文章只是想用來記錄怎麼使用 getStaticPaths,所以省略了很多東西。例如在 getStaticPaths 中應該是不太會把所有 paths 都寫死,以部落格為例子的話,通常是讀取 posts 資料夾中所有的檔案,接著去掉副檔名後用檔案名稱來當作 path。

另外,其實這個網站就是用 Next.js 寫的,部落格的部分也有使用 getStaticPaths,雖然寫得可能沒有很好,但如果讀者有興趣的話可以到這裡看看。