chakkun1121's blog

nextjsをgithub pagesにデプロイする方法

投稿日:2023/8/31

はじめに

この記事ではnextjs(app directory使用)をgithub pagesにデプロイする方法について書きます。ただし、nextjsについては書きません。

前提条件

  • nextjs製のアプリを作成した(ローカルでは動く)
  • github pagesにデプロイしたい
  • パッケージマネージャはpnpmを利用している
  • しかし、pnpm-lock.yamlは(gitingoreで)除外している

本題

最初にgithub actionsの設定をします。(github actionsについては各自調べてください。)

次のように .github/workflows/nextjs.yml を作成します。

1# .github/workflows/deploy.yml
2
3on:
4  push:
5    branches: ["main"]
6  workflow_dispatch:
7
8permissions:
9  contents: read
10  pages: write
11  id-token: write
12
13concurrency:
14  group: "pages"
15  cancel-in-progress: false
16
17jobs:
18  # Build job
19  build:
20    runs-on: ubuntu-latest
21    steps:
22      - uses: actions/checkout@v4
23      - name: Setup Node.js environment
24        uses: actions/setup-node@v4
25        with:
26          node-version: latest
27      - name: Install pnpm
28        run: npm install -g pnpm
29      - name: Install dependencies
30        run: pnpm install
31      - name: Build
32        run: pnpm next build
33      - name: Upload artifact
34        uses: actions/upload-pages-artifact@v2
35        with:
36          path: ./out
37
38  # Deployment job
39  deploy:
40    environment:
41      name: github-pages
42      url: ${{ steps.deployment.outputs.page_url }}
43    runs-on: ubuntu-latest
44    needs: build
45    steps:
46      - name: Deploy to GitHub Pages
47        id: deployment
48        uses: actions/deploy-pages@v2

追記内容

  • 2024-01-30追記:バージョンアップしました。
  • 2024-02-10追記:何故か今までの方法では動かなかったので変更しました。実験リポジトリ (コミットメッセージが雑なのはお許しください。)

追記終了

このファイルを設置後の大体のディレクトリ構成

1.github
2  └ workflows
3    └ nextjs.yml
4app (本体)
5  ├ layout.tsx (or layout.js)
6  └ ... その他諸々
7out (ビルド後のファイル(自動生成))
8... その他諸々

これで大体の場合は対処できます。

問題の処理

この方法だけだと、ダイナミックルーティング(動的ルーティング)(大かっこ([])で囲まれたフォルダーを利用する)を使用しているとそのページが表示できません。理由としては、その場合はparamsを利用することになりますが、まだそのparamsに何が来るかがビルド段階では決定できないためレンタリングできません。しかし、github pagesにデプロイ仕様としているのであれば、ビルド時にどのparamsが入る可能性があるのかは予想できるはずです。(そうでなければgithub pagesは諦めてください。)そのため、ビルド時にparamsに何が入る可能性があるのかを明示的に教えなければいけません。(他のところにリンクがあるからといって、自動的にはやってくれません。)そのため、ダイナミックルーティングを利用しているpage.tsxは以下のようにgenerateStaticParamsをエクスポートします。

1// ブログページでの利用例
2export default async function Page({ title }: { title: string }) {
3  const data = await getData(title);
4  return <div>{data}</div>;
5}
6export async function generateStaticParams() {
7  return await allArticlesData().then((data) => {
8    return data.map((article) => {
9      return {
10        params: {
11          title: article.title,
12        },
13      };
14    });
15  });
16}

2023-10-24追記

next.js v13.5以降では、Page <ページパス> is missing exported function "generateStaticParams()", which is required with "output: export" config.と警告してくれるようになりました。これが出た場合は上記の通りgenerateStaticParamsを追加してください。(ただし、何故かバグで表示されることもあるので怪しかったら実際にビルドしてみてください。)

追記終了

このようにすることでビルド時にどのtitleが来るのかを決定することができます。ただし、これはビルド時にすべてのparamsを決定することになるので、ビルド後に変更することはできません。また、paramsの数が多い場合はビルド時間が長くなることはありますが、ビルドは放置しておけば終わるので気長に待ちましょう。(これをクライアントのリクエストが来てからだとページの表示が遅くなりますが、ビルド時にやってしまえばページの読み込みは早くなります。)

おわりに

このようにすることでNext.js製のアプリをgithub pagesにビルドできます。ちなみにこのブログもこの方法を利用してgithub pagesにデプロイしています。