nero15.devは、サッカー情報を中心に技術記事なども配信するメディアプラットフォームです。1から開発するにあたり、技術スタックの選定は重要な決断でした。
本記事では、フロントエンドフレームワークとしてNext.jsを選択した理由と、その判断に至るまでの思考プロセス、そして実際に開発してハマったポイントを共有します。
このプロジェクトはAI駆動開発を前提としています。今後の機能追加や保守においても、AIを活用したコード生成は重要なファクターになると考えています。
実際に業務でAIを使ってコード生成をしてきた経験から言えることは、フロントエンドコードの生成はReactが圧倒的に生成精度が高いという点です。Claude、ChatGPT、GitHub Copilotなど、どのAIツールを使っても、Reactのコンポーネント生成は非常に高品質で、そのまま使えるケースが多い。プロンプトを少し調整するだけで、期待通りのコードが返ってくる。
Vue.jsやSvelteも選択肢としてはありましたが、AIによるコード生成の品質と速度を考えると、React(Next.js)は現時点で最も開発効率が高いフレームワークだと判断しました。特に個人開発で限られた時間の中で開発を進めるには、この「AIとの相性」は無視できない要素でした。
Next.jsはSEO対策に必要な機能が非常に充実しています。メディアサイトである以上、検索流入は生命線なので、この点は最重要視しました。
App Routerでは、各ページでmetadata
オブジェクトをエクスポートするだけで、タイトル、description、OGPタグなどを簡単に設定できます。
export const metadata: Metadata = {
title: 'ミラノダービー | 試合分析',
description: 'ミラノダービーの詳細な戦術分析',
openGraph: {
title: 'ミラノダービー | 試合分析',
description: 'ミラノダービーの詳細な戦術分析',
images: ['/og-image.jpg'],
},
twitter: {
card: 'summary_large_image',
},
}
検索エンジンに記事の構造を正確に伝えるため、JSON-LD形式の構造化データを埋め込むことで、リッチリザルトの表示確率が上がります。
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
author: {
'@type': 'Person',
name: 'nero15',
},
datePublished: post.date,
}
app/sitemap.ts
とapp/robots.ts
を作成するだけで、動的にサイトマップとrobots.txtを生成できます。記事が増えても自動的に反映されるため、手動管理の必要がありません。
next/og
を使えば、記事タイトルから動的にOG画像を生成できます。SNSでのシェア時に視覚的に魅力的な画像を自動生成できるのは、メディア運営において大きなメリットです。
個人的に、このプロジェクトではSSRが必須だと考えていました。
静的生成(SSG)だけでは、記事の更新を即座に反映できません。試合結果や移籍情報など、タイムリーな情報を扱うメディアでは、記事を公開したらすぐに検索エンジンにクロールされ、インデックスされる必要があります。毎回ビルドを走らせるのは現実的ではありません。
Next.jsのSSRでは:
ISRについては、正直なところあまり知見がなかったため、今回はリリースまでの開発速度を優先するために深く調査しませんでした。これは今後検討したい課題です。
SSGとSSRを併用できるのもNext.jsの強みです。トップページはSSG、記事詳細ページはSSRと、ページごとに最適なレンダリング方法を選択できるのは、パフォーマンスとSEOのバランスを取る上で重要でした。
インフラにはGCPのCloud Runを採用しました(この選択理由については別記事で書く予定です)。
Next.jsはコンテナ化が容易で、Cloud Runとの相性が非常に良いです。
next build
とnext start
でSSRアプリケーションをコンテナとして起動Vercelも検討しましたが、Cloud Runの方が:
という点で優れていると判断しました。個人開発でも将来的なスケールを見据えた時、GCPの方が柔軟性が高いと感じています。
app/posts/[slug]/page.tsx
のような形で、直感的にルーティングを定義できます。App Routerの導入により、Reactの最新機能(Server Components、Streaming SSRなど)も活用可能です。
特に、AIにコードを生成させる際、「このパスに新しいページを作って」という指示だけで、適切なディレクトリ構造とファイルを生成してくれるのは、開発速度の面で大きなメリットでした。
マークダウン記事を扱うための便利なライブラリが充実しています:
gray-matter
: frontmatterのパースremark
/ rehype
: マークダウンのHTML変換と拡張next-mdx-remote
: MDXのサポートこれらをNext.jsと組み合わせることで、柔軟な記事管理システムを短期間で構築できました。AIに「こういう記事システムを作りたい」と伝えれば、これらのライブラリを組み合わせた実装を提案してくれます。
実際に開発していて、一番ハマったのがNext.jsの環境変数の扱いです。
正直に言うと、私は本職がバックエンドエンジニアで、Next.jsを使って一から構築した経験はありませんでした。これまでのキャリアでNext.jsをガッツリ触ったことがなく、今回が初めての本格的な構築でした。
Next.jsは**ビルド時に環境変数を埋め込む(インライン化する)**という仕様になっています。
具体的には:
next build
実行時にprocess.env.NEXT_PUBLIC_*
などの環境変数が、JavaScriptバンドルに文字列として直接埋め込まれるこれはwebpack DefinePluginによる置換処理で、process.env.NEXT_PUBLIC_API_URL
のような記述が、ビルド時に"https://api.example.com"
という文字列リテラルに置き換わってしまうのです。
通常のバックエンド開発では:
という流れが当たり前です。しかしNext.jsでは、ビルド時に環境変数が決まってしまうため:
という状況に陥りました。インフラ側の設定をいくら見直しても解決せず、かなり時間を溶かしました。
結論として、GitHub Actionsのビルドステップで環境変数をセットするという対応をしました。
具体的には、GitHub Actionsのワークフロー内で:
docker build
時に--build-arg
で環境変数を渡すARG
として受け取り、ENV
として設定next build
実行時に環境変数が埋め込まれるという流れにしています。
この辺の具体的な実装については、別途記事にする予定です。GitHub ActionsとCloud Runを組み合わせたCI/CD環境の構築は、意外とハマりどころが多いので、同じ境遇の人の参考になればと思っています。
Next.jsの環境変数は、Reactアプリケーション特有の「ビルド時最適化」の産物です。セキュリティ面でも、クライアント側で動くコードに秘密情報を埋め込むリスクを減らすための設計になっています。
バックエンド開発の常識が通用しない部分があり、フロントエンド(特にReactエコシステム)の特性を理解する良い機会になりました。
nero15.devの開発において、Next.jsは最適な選択でした。
特に:
一方で、フロントエンド特有の「ビルド時最適化」の仕組みは、バックエンドエンジニア視点では直感的でない部分もありました。しかし、これらの学びも含めて、Next.jsを選んで良かったと感じています。
最終更新: 2025年10月4日