Page Router を使った Next.js の全ページのパスを取得する方法

kaori
kaori

Page Router を使った Next.js のページリストを取得する

​ 動的ページルーティングを含む Next.js のアプリケーションを S3 と CloudFront を使って静的ホスティングするとき、Next.js のページ一覧があると NotFound にすべきかどうかの判断がしやすくなるので使っています。 ​

検証環境

  • Next.js 14.0.3
  • Page Router を使用 ​
├── next-env.d.ts
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── favicon.ico
│   ├── next.svg
│   └── vercel.svg
├── src
│   ├── pages
│   │   ├── 404.tsx
│   │   ├── _app.tsx
│   │   ├── _document.tsx
│   │   ├── index.tsx
│   │   └── sample
│   │       ├── [id]
│   │       │   └── index.tsx
│   │       └── index.tsx
│   ├── styles
│   │   └── globals.css
│   └── util.ts
├── tailwind.config.ts
└── tsconfig.json

指定したディレクトリ配下のファイル名をすべて取得する

​ ビルド時にページとして出力されてしまうような場所(今回の場合はpages配下)以外なら、どこに書いても問題ありません。今回はsrc/util.tsに処理を書いていきます。 ​

// src/util.ts
import fs from 'fs';
import path from 'path';
function getFilesInDirectory(dir: string): string[] {
  const entries = fs.readdirSync(dir, { withFileTypes: true });

  const files = entries
    .filter((fileDirent) => fileDirent.isFile())
    .map((fileDirent) => path.join(dir, fileDirent.name));

  const directories = entries.filter((fileDirent) => fileDirent.isDirectory());

  for (const directory of directories) {
    files.push(...getFilesInDirectory(path.join(dir, directory.name)));
  }

  return files;
}

動的ページパスを抽出する

​ 上のファイル名一覧を利用して動的なページパスの一覧を取得します。 ​

export function getDynamicPageList() {
  const pagesDirectory = path.resolve(process.cwd(), 'src', 'pages');
  const pageFiles = getFilesInDirectory(pagesDirectory);

  const dynamicPageList = pageFiles.filter(
    (file: string) =>
      ['.js', '.jsx', '.ts', '.tsx'].some((ext) => file.endsWith(ext)) &&
      file.includes('[') &&
      file.includes(']')
  );

  return dynamicPageList.map((p) =>
    p.replace(pagesDirectory, '').replace(/\/index\.tsx$/, '/')
  );
}

​ 拡張子が['.js', '.jsx', '.ts', '.tsx']のファイルで[]を含んでいるものだけに絞り込み、末尾のindex.tsxをスラッシュに置換しています。このあたりを調整することで任意のファイルパスを取得してみてください。

実行結果

getDynamicPageList()を実行すると["/sample/[id]/"]が取得できました。