Next.js 15 App Routerでのブログ最適化: 静的生成による90%以上のパフォーマンス改善

Next.js 15のStatic Site Generationを活用して、ブログサイトのパフォーマンスを大幅に改善した実装事例を解説。TTFBを90%以上改善し、SEOとユーザー体験を向上させた具体的な手法を紹介します。

はじめに:パフォーマンスの課題

このブログサイトはNext.jsで構築しており、ソースコードをGitHubで公開しています。記事のコンテンツは、柔軟な更新と保守性を考慮して分割されたJSONファイルで管理しています。しかし、この管理方式には予期せぬ課題がありました。複数のJSONファイルを個別に読み込んでレンダリングする必要があるため、ページの読み込み時間が著しく遅くなってしまったのです。

具体的な計測では、Time to First Byte(TTFB)が1,800ms近くかかっており、ユーザー体験とSEOの両面で大きな課題となっていました。また、OpenGraphタグの未対応により、SNSでの記事共有時の表示も最適化されていない状況でした。TTFBの重要性については、Core Web Vitalsとパフォーマンス指標で詳しく解説されています。

実装前の計測値(/blog/downloading-videos-with-ffmpeg-m3u8):

• TTFB: 1,819ms • Loading time: 1,823ms • Cache-Control: private, no-cache, no-store • OpenGraph: 未対応

この記事では、Next.js 15のStatic Site Generation(SSG)を活用してこれらの課題を解決し、パフォーマンスを大幅に改善した実装について説明します。分割JSONによる柔軟なコンテンツ管理の利点を活かしつつ、高速なページ表示を実現する方法を紹介していきます。

Static Site Generationによる最適化の実装

これらの課題に対し、私たちはNext.js 15のStatic Site Generation(SSG)を活用した解決策を実装しました。Next.js App Routerでは、単一のHTMLファイルごとに生成を行うことで、不要なJavaScriptコードのクライアントサイドでのロードを避けることができます。この最適化により、バンドルサイズの削減と読み込み時間の短縮を実現しています。

コアとなる実装

app/blog/[slug]/page.tsx
1export const dynamicParams = false;
2
3export async function generateStaticParams() {
4  const posts = await getAllPosts();
5  return posts.map(post => ({
6    slug: post.slug
7  }));
8}
9
10export async function generateMetadata({ params }: Props) {
11  const post = await getPost(params.slug);
12  return {
13    title: post.meta.title,
14    description: post.meta.description,
15    openGraph: {
16      title: post.meta.title,
17      description: post.meta.description,
18      type: 'article'
19    }
20  };
21}
22
23export default async function PostPage({ params }: Props) {
24  const post = await getPost(params.slug);
25  return <PostContent post={post} />;
26}

実装のポイント

実装の主要なポイントは、Dynamic Routesに基づいて以下のように構成しています:

1. 静的パラメータの生成 generateStaticParams 関数は、ビルド時に生成する記事パスを定義します。generateStaticParams内でのデータ取得(fetch)は自動的にメモ化されるため、同じデータに対する重複したリクエストを効率的に処理できます。

2. 動的パラメータの制御 dynamicParams = false を設定することで、generateStaticParamsで定義されていないパスへのアクセスを制御します。これにより、定義されていないURLに対して確実に404ページを返すことができます。

3. Server Componentsの活用 Server Componentsは、ビルド時に実行され、従来の静的サイト生成と同様に動作します。これにより、初期ページロード用の静的HTMLと、クライアントナビゲーション用の静的ペイロードの両方を生成できます。

最適化の戦略

この実装による最適化のポイントは以下の通りです:

1. ビルド時の最適化

  • 分割JSONファイルの読み込みをビルド時に行い、実行時のファイルI/Oを完全に排除
  • generateStaticParams内のデータ取得は自動的にメモ化され、ビルド時間を最適化
  • Automatic Static Optimizationにより、各ルートに対して個別のHTMLファイルを生成し、不要なJavaScriptの読み込みを防止

2. 柔軟な静的生成戦略 開発時(next dev)とプロダクション時(next build)で異なる動作を実現:

  • 開発時:ルートへのナビゲーション時にgenerateStaticParamsを実行
  • ビルド時:該当するLayoutsやPagesの生成前にgenerateStaticParamsを実行

3. キャッシュとCDNの最適化 静的生成されたページはCDNでキャッシュ可能となり、Cache-Controlヘッダーも'public'に設定されます。これにより、CDNキャッシングとエッジケーシングを活用した効率的なコンテンツ配信が可能になります。

パフォーマンス改善の成果

この実装により、以下のような大幅なパフォーマンス改善を達成しました。特にTTFBとローディングタイムについては、90%以上の改善を実現しています。これらの計測は、Core Web Vitals reportの基準に基づいて実施しました。

実装後の計測値:

  • TTFB: 174ms(90.4%改善)
  • Loading time: 175ms(90.4%改善)
  • Cache-Control: public, max-age=0, must-revalidate
  • OpenGraph: 完全対応

この改善により、以下のような効果が得られました。詳細はPerformance & Core Web Vitalsについてを参照してください。

パフォーマンス向上 実行時のファイルI/Oが削減され、CDNキャッシュを効率的に活用できるようになりました。これにより、TTFBが大幅に改善し、ユーザー体験が向上しました。

SEO改善 SEOとメタデータの最適化に基づき、完全な静的HTMLを生成し、メタデータも事前に用意することで、検索エンジンのクローラーがコンテンツを効率的に取得できるようになりました。

運用の簡素化 デプロイとエラー処理が単純化され、インフラ管理の負担も軽減されました。事前生成により、実行時のエラーリスクも大幅に減少しています。

モニタリングと継続的な改善

Next.jsのパフォーマンスモニタリングに基づき、以下の指標を継続的に監視しています:

  • TTFB: 目標200ms以下
  • コンテンツ圧縮率
  • キャッシュヒット率
  • ビルド成功率: 99.9%以上
  • メタデータの整合性

これらの指標を監視することで、パフォーマンスの低下を早期に検知し、必要な対策を講じることができます。

制限事項と考慮点

Static Exportの制限事項として、以下の機能は使用できません:

1. 動的機能の制限

  • dynamicParams: true を使用する動的ルート
  • generateStaticParams() のない動的ルート
  • Requestに依存するRoute Handlers
  • Cookiesの使用
  • ミドルウェアの使用

2. データ更新の制限

  • Incremental Static Regeneration (ISR)は使用不可
  • Server Actionsは使用不可
  • 実行時のリライトやリダイレクトは不可

これらの制限は、開発時(next dev)にエラーとして検出されます。制限された機能を使用しようとすると、rootレイアウトでdynamic = 'error'を設定した場合と同様のエラーが発生します。

まとめと今後の展望

Next.js 15のStatic Site Generationの導入により、JSONブロックによる効率的な記事データ管理と、高いパフォーマンスの両立を実現できました。90%以上のパフォーマンス改善は、当初の想定を超える成果でした。

特筆すべきは、App Routerの新しい機能を活用することで、より直感的なルーティングと効率的なデータ取得が可能になった点です。generateStaticParamsとServer Componentsの組み合わせにより、SEOとパフォーマンスの両面で最適化されたブログシステムを構築できました。

この実装は、コンテンツの拡充とシステムの進化の両面で、持続可能な発展を可能にする基盤となっています。実装の詳細はGitHubリポジトリで公開しており、今後も継続的なモニタリングと最適化を行い、さらなる改善を目指していきます。