Skip to content

perf: fallback: 'blocking' とISRでNotion APIの呼び出し回数を削減 - #201

Open
Riku-0801 wants to merge 1 commit into
mainfrom
feat/reduce-notion-api-with-isr
Open

perf: fallback: 'blocking' とISRでNotion APIの呼び出し回数を削減#201
Riku-0801 wants to merge 1 commit into
mainfrom
feat/reduce-notion-api-with-isr

Conversation

@Riku-0801

@Riku-0801 Riku-0801 commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

関連issue

なし(fallback: 'blocking' でNotion API呼び出しを削減する依頼)

やったこと

背景・課題

ブログの動的ルート(blog/[id] / blog/tag/[tag] / blog/writer/[writer])が getStaticPaths全パスを事前生成しており、記事数に比例してNotion APIを大量に呼び出していました。特に blog/[id] は記事ごとに getBlocks / getPage / getArticles(おすすめ用にDB全件クエリ)を実行します。さらに .github/workflows/build.yml6時間ごとに全ビルドが走るため、この呼び出しが繰り返されていました。

変更内容

  • 動的ルートを fallback: 'blocking'getStaticPaths{ paths: [], fallback: "blocking" } に変更。ビルド時の事前生成をやめ、リクエスト時にオンデマンド生成 → ISR(revalidate: 3600 = 1時間)でキャッシュ。tag / writer の getStaticPaths から不要になった getDatabase 呼び出しも削除。
  • blog/[id] の重複クエリ削減:公開記事一覧(getArticles())を「記事の存在確認」と「おすすめ記事」で使い回し、重複していた getArticles 呼び出しを1回に集約。fallback: 'blocking' では任意のIDでアクセスされ得るため、公開記事に含まれないID(非公開・存在しない・公開日前)は notFound で404に。
  • tag / writer の404対応:公開記事が0件のタグ/ライター(存在しない値への直接アクセス等)は404を返すように。
  • 静的ページのISR化:Notionを参照する top / products / achievements / blog(一覧) にも revalidate を付与。
  • 画像ユーティリティのガードfallback: 'blocking' では getStaticProps がリクエスト時(Vercelのサーバーレス=読み取り専用FS)で実行され、public/ への書き込みやフォント読み込みに失敗します。createOGPImage / cacheRemoteImage のファイル操作を try/catch で保護し、失敗時はビルド時生成物のパス(CDN配信)/元のNotion URLにフォールバックしてページ生成を継続するようにしました。revalidate を1時間にしているのはNotion画像URLの有効期限(約1時間)と揃える意図もあります。
  • revalidate の値は src/constants/index.tsISR_REVALIDATE_SECONDS に集約。

効果

  • 通常ビルドで生成するのは静的ページ+動的ルートの雛形のみになり、ビルドごとのNotion API呼び出しが大幅に削減されます(記事数 × 数回 → 数回程度)。
  • 記事詳細はオンデマンド生成+1時間キャッシュ。新規記事もリビルドを待たずに到達可能になります。

確認事項 / レビュー観点

  • tsc --noEmit / next lint ともにエラーなし。
  • ⚠️ 実行時(サーバーレス)の画像挙動はVercelのプレビューデプロイで確認をお願いします。特に「前回ビルド以降に追加された新規記事の本文中画像/OGP」が、次回ビルドまでの間どう表示されるか(元URLフォールバック or 一時的に未表示)。
  • 💬 revalidate の間隔(現状1時間)は運用に合わせて調整可能です。ISR_REVALIDATE_SECONDS 一箇所で変更できます。
  • 補足: .prettierrc.jsparser: "typescript" | "scss" は不正値(JS評価で 0)になっており prettier がエラーになります。本PRの対象外のため未修正ですが、別途修正推奨です。

🤖 Generated with Claude Code

ブログの動的ルート([id]/tag/writer)はビルド時に全パスを事前生成しており、
記事数に比例してNotion APIを大量に呼び出していた(各記事でgetBlocks/getPage/
getArticlesを実行)。6時間ごとの定期ビルドでこれが繰り返されていた。

- 動的ルートのgetStaticPathsをpaths:[] + fallback:'blocking'に変更し、
  リクエスト時のオンデマンド生成 + ISR(revalidate: 1時間)でキャッシュ
- blog/[id]では公開記事一覧を存在確認とおすすめ記事で使い回し、
  重複していたgetArticles呼び出しを削減。非公開/存在しないIDは404に
- tag/writerは公開記事が無い場合に404を返すよう変更
- Notionを参照する静的ページ(top/products/achievements/blog)にも
  revalidateを付与しISR化
- fallback:'blocking'ではgetStaticPropsがリクエスト時(サーバーレス)で
  実行されpublic/へ書き込めないため、createOGPImage/cacheRemoteImageの
  ファイル書き込みをガードし、失敗時はビルド時生成物/元URLにフォールバック

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
jackweb Ready Ready Preview, Comment Jun 11, 2026 3:08pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant