開発からデプロイメントまで:EdgeOne Pages における Next.js フルスタックのベストプラクティス

このガイドでは、高性能なNext.jsフルスタックアプリケーションの構築と、コード品質やアプリケーション速度を犠牲にすることなく開発ワークフローの最適化に焦点を当てています。
今後のセクションでは、プロジェクトアーキテクチャ、環境設定、ルーティング戦略、効率的なデータ取得技術について詳しく検討します。これらのストプラクティスにより、EdgeOne PagesでシームレスにNext.jsフルスタックアプリケーションをデプロイでき、エッジコンピューティングの力を活用して優れたパフォーマンスと世界規模のアクセシ。
ディレクトリ構造の推奨事項
以下のディレクトリ構造は、推奨するNext.jsハイブリッドレンダリングテンプレートを表しています。この慎重に整理されたアーキテクチャは、スケーラブルなフルスタックアプリケーションを構築する開発者にとって最適な基盤として機能します:
next-mix-template/
├── src/ # Next.js App Router
│ │ ├── layout.tsx
│ │ ├── page.tsx # ホームページコンポーネント
│ │ ├── ssr/ # SSRデモンストレーションページ
│ │ ├── isr/ # ISRデモ
│ │ ├── ssg/ # SSGデモンストレーションページ
│ │ ├── streaming/ # ストリーミングデモンストレーションページ
│ │ ├── node-functions/# node function デ
│ │ ├── edge-functions/# edge function デモンストレーションページ
│ │ ├── api/ # APIルート
│ │ └── globals.css # Reactコンポーネント
│ │ ├── ui/
│ │ ├── Header.tsx
│ │ ├── Hero.tsx
│ │ ├── Features.tsx
│ │ └── FeatureCard.tsx
│ └── lib/ # ユーティリティ関数
├的リソース
├── package.json # プロジェクト設定
├── next.config.ts # Next.js設定
├── tailwind.config.ts
└── components.json # shadcn/ui設
このプロジェクトは、EdgeOne Pagesとシームレスに統合する2つの専用バックエンド function ディレクトリを持つ標準的なNext.js App Routerアーキテクチャに従っています:
edge-functions
ディレクトリは、EdgeOne Pagesのエッジコンピューティング機能のエントリーポイントとして機能します。軽量なリクエストをここに配置することで、ユーザーに最も近いエッジノードから直接実行されるため、高速な応答時間の恩恵を受け、優れた速度とパフォーマンスを実現できます。
EdgeOne Pagesはnode-functions
を提ており、これは豊富なNode.jsパッケージエコシステムを活用できる集中型 function デプロイメント環境です。これに全なNode.js機能を必要とするより複雑な機能を迅速に実装でき、同時に合理化された開発体験を維持できます。
edge-functionsとnode-functionsの詳細については、公式ドキュメントをご参照ください。
ルートとAPI統合
EdgeOne Pagesでは、ドメインベースのパスルーティングを介してページとAPIエンドポイントに直接アクセスできます。マッピングは一貫したパターンに従い、ファイルの場所がURLパ直接対応します。例えば、/app/
node-functions
/get-users/
index.js
は{domain}/get-users
でアクセス可能になります。
このプラットフォームは、自動パスマッピングを備えた直感的な特徴としています:
主な機能:
- 自動パスマッピング:ファイルシステム構造がURLルートに直接変換されます
- ゼロ設定:手動でのルーティング設定は不要です
- 統一ルート管理:ページとAPIルートの両方をシームレスに処理します
- ポートフリーアクセス:直接ドメインベースルーティングによりポート指定が不要です
Project structure:
/app/node-functions/get-users/index.js
/app/node-functions/create-user/index.js
/app/node-functions/products/[id].js
/app/edge-functions/get-products/index.js (edge)
Access method:
https://yourdomain.com/get-users → run get-users/index.js
https://yourdomain.com/create-user → run create-user/index.js
https://yourdomain.com/products/123 → run products/[id].js
https://yourdomain.com/get-products → run get-products/index.js (edge)
ページレンダリングとデータ取得
Next.jsは複数のレンダリング戦略を提供し、それぞれ異なるデータ取得メカニズムを持っています。EdgeOne PagesはNext.jsの3つの主要なレンダリングモード(静的サイト生成(SSG)、サーバーサイドレンダリング(SSR)、インクリメンタル静的再生成(ISR))を包括的にサポートし、開発者が同じアプリケーション内ですべてのアプローチを活用できます。
1. App Routerデータ取得(Next.js 13+)
新しいApp Routerは、データ取得に異なるアプローチを採用しています。詳細については、Next.jsの公式ドキュメントをご覧ください。
// app/products/page.js
// デフォルトの静的レンダリング
async res = await fetch('https://api.example.com/products',: 'force-cache' // デフォルトキャッシュ
})
return res.json()
}
export default async function ProductsPage() {
const products = await getProducts()
return (
<div>
{products.map(product => (
<div key={product.id}>{product.name}</div>
))}
</div>
)
}
revalidate: 0
を設定すると、毎回のリクエストでデータ取得にサーバーサ使用することが強制されます。
// app/live/page.js
// 動的レンダリング(getServerSidePropsに類似)
async function getLiveData() {
const res = await fetch('https://api.example.com/live', {
cache: 'no-store', // キャッシュなし、各リクエストで新しいデータを取得
// または次を使用
next: { revalidate: 0 }
})
return res.json()
}
// App RouterでのISR
async function getDataWithISR() {
const res = await fetch('https://api.example.com/data', {
next: { revalidate: 60 } // 60秒後に再検証
})
return res.json()
}
// pages/dashboard.js
// 静的とクライアントサイドデータ取得の組み合わせ
export async function getStaticProps() {
// あまり変更されないデータを取得
const staticData = await fetch('https://api.example.com/config')
const
return {
props: { config },
revalidate: 3600, // 1時間
}
}
function Dashboard({ config }) {
// クライアントがリアルタイムデータを取得
const { data: liveData } = useSWR('/api/live-stats', fetcher, {
refreshInterval: 5000
})
return (
<div>
<h1>{config.title}</h1>
{liveData && <div>オンラインユーザー: {liveData.onlineUsers}</div>}
</div>
)
}
2. getStaticProps(静的生成)
ビルドプロセス中にデータを取得し、静的なHTMLページを生成します。比較的安定しており、頻繁な更新を必要としないコンテンツに最適です。
// pages/products.js
export async function getStaticProps() {
const res = await fetch('https://api.example.com/products')
const products = await res.json()
return {
props: {
products,
}
}
}
export default function Products({ products }) {
return (
<div>
{products.map(product => (
<div key={product.id}>{product.name}</div>
))}
</div>
)
}
3. getServerSideProps(サーバーサイドレンダリング)
サーバーサイドレンダリング(SSR)は、毎回のリクエストでサーバーサイドでデータを取得します。この方法は、リアルタイムデータの更新やリクエスト固有の情報へのアクセスが必要なページに最適です。
// pages/user/[id].js
export async function getServerSideProps(context) {
const { id } = context.params
const { req, res, query } = context
const cookies = context.req.cookies
const userData = await fetch(`https://api.example.com/users/${id}`)
const user = await userData.json()
if (!user) {
return {
notFound: true,
}
}
return {
props: {
user,
}
}
}
export default function User({ user }) {
return <div>Welcome, {user.name}!</div>
}
使用例:LinkedIn(linkedin.com)
4. ISR(インクリメンタル静的再生成)
revalidate
パラメータは、インクリメンタル静的再生成(ISR)を有効にし、ルールベースのオンデマンドページデータ更新を提供します。
export async function getStaticProps() {
const res = await fetch('https://api.example.com/blog')
const posts = await res.json()
return {
props: {
posts,
},
// Three ISR strategies
revalidate: 60, // Regenerate after a time interval in seconds
// or
revalidate: false, // Disable ISR and only generate it at build time
// or
revalidate: true, // On-demand ISR (configuration required)
}
}
使用例:Dev.to(dev.to)人気コンテンツは5分ごとに更新
方法の比較と決定マトリックス
方法 | 実行時間 | 使用例 | SEO | パフォーマンス |
getStaticProps | ビルド時 | 静的コンテンツ | ✅ 優秀 | ⚡ 最速 |
getServerSideProps | 毎回のリクエスト | 動的コンテンツ/パーソナライゼーション | ✅ 良好 | 🐢 低速 |
ISR (revalidate) | ビルド時 + 定期更新 | 半静的コンテンツ | ✅ 良好 | ⚡ 高速 |
App Router fetch | 設定に依存 | 柔軟 | ✅ 良好 | 🔧 設定可能 |
開発者向け決定マトリックス:
ウェブサイトタイプ | 推奨戦略 | 代表的サイト | 主な考慮事項 |
ドキュメント/ブログ | SSG | Next.js Docs, MDN | SEO、パフォーマンス、コスト |
Eコマースプラットフォーム | SSR/ISR | Amazon, Shopify | リアルタイム在庫、パーソナライゼーション |
ソーシャルメディア | SSR | Twitter, LinkedIn | リアルタイム更新、パーソナライゼーション |
ニュースメディア | ISR/SSR | CNN, BBC | タイムリー性、SEO |
SaaSマーケティングサイト | SSG/ISR | Stripe, Slack | パフォーマンス、コンバージョン率 |
企業ウェブサイト | SSG | Apple, Microsoft | ブランドプレゼンテーション、パフォーマンス |
オンライン教育 | ISR | Coursera, Udemy | コンテンツ更新、SEO |
ストリーミングメディア | SSR | Netflix, Spotify | パーソナライゼーション、リアルタイムレコメンデーション |
環境変数管理
EdgeOne Pagesは環境変数管理の規約に準拠しています:
- パブリック変数:`NEXT_PUBLIC_`プレフィックスが付いた環境変数は、クライアントサイドバンドルに埋め込まれ、ブラウザコードでアクセス可能になります。これらの変数には、機密でない情報のみを含める必要があります。
- 保護された変数:APIキー、認証トークン(例:`AI_TOKEN`)、その他の認証情報などの機密情報については、`NEXT_PUBLIC_`プレフィックスを省略します。これらの変数はサーバーサイドのみに留まり、クライアントサイドコードでの露出から保護されます。
この一貫した準的なNext.js環境変数システムとの互換性を維持しながら、設定値の可視性とセキュリティを管理できます。
# プライベート環境変数
OPENAI_API_URL=
OPENAI_API_KEY=
DB_HOST=
DB_PORT=
DB_USER=
DB_PASSWORD=
DB_NAME=
# パブリック環境変数
NEXT_PUBLIC_AUTHOR=
NEXT_PUBLIC_EMAIL=
通常、単一の.env.localファイルで十分です。ただし、開発環境(next dev)や本番環境(next start)に対して、それぞれ別途デフォルト設定を追加したい場合があります。
Next.jsでは、.env(全環境用)、.env.development (開発環境用)、.env.production(本番環境用)でデフォルト値を設定できます。.env.localは常にデフォルト設定を上書きします。
EdgeOne Pagesにデプロイする際は、ローカルの.
env
ファイルと一致する環境変数をEdgeOneコンソールで設定する必要があります。EdgeOne PagesはNext.jsの規約に従い、NEXT_PUBLIC_
のプレフィックスが付いた変数はクライアントサイドのコードに埋め込まれ、このプレフィックスがない変数はサーバーサイドで保護されたままになります。
注意:セキュリティのため、APIキーやトークンなどの機密情報が誤ってリポジトリにコミットされることを防ぐために>
env
*
ファイルを.gitignore
に追加してください。
まとめ
EdgeOne PagesはNext.jsフルスタックプロジェクトに対して包括的なネイティブサポートを提供し、静的サイト生成(SSG)、サーバーサイドレンダリング(SSR)、インクリメンタル静的再生成(ISR)、API Routesなど、様々なNext.jsのコア機能と完全に互換性があります。開発者は複雑な設定調整を行うことなく、Next.jsフレームワークのすべての利点を活用でき、柔軟なレンダリング戦略の選択と効率的なフルスタック開発体験を可能にします。
EdgeOne Pagesの効率的なデプロイメントプロセスのおかげで、開発チームはEdgeOne CLI操作やCI/CD統合を通じて、Next.jsアプリケーションをグローバルエッジネットワークに迅速にデプロイできます。このシームレスなデプロイメント体験は、運用の複雑さを大幅に削減するだけでなく、エッジコンピューティング機能を通じて優れたパフォーマンスと信頼性を提供し、開発者がインフラ管理と最適化を心配することなく、ビジネスロジックの実装により集中できるようにします。