🔗 Next.js Commerce 統合戦略 - 実装ガイド
無駄のないインストール・統合計画
既存BFFアーキテクチャを活かしたスマート統合アプローチ
🎯 統合方針・基本原則
核となる戦略
統合原則:
現行保持: Cloudflare Workers BFF + Firebase Auth + PII分離
新規採用: Next.js Commerce UIコンポーネント + 最適化パターン
アプローチ: 段階的部分統合(フル移行なし)
最適化目標:
- UI/UX品質向上: Next.js Commerce標準レベル
- 開発効率: 共通コンポーネント活用で+30%
- 保守性: TypeScript + 設計パターン導入
- 既存リスク: 最小化(アーキテクチャ変更なし)
📦 段階別インストール戦略
Phase 0: 環境準備(1日)
依存関係分析・抽出
# Next.js Commerce リポジトリクローン(参考用)
git clone https://github.com/vercel/commerce.git commerce-reference
cd commerce-reference
# 必要コンポーネント特定
find components -name "*.tsx" | grep -E "(product|cart|checkout)" > components-list.txt
find lib -name "*.ts" | grep -E "(shopify|types)" > lib-files.txt
現行プロジェクト準備
# 現在のプロジェクトで必要パッケージ追加
cd /path/to/contents-print
npm install @tailwindcss/typography class-variance-authority clsx tailwind-merge
npm install @radix-ui/react-* # 必要なRadix UIコンポーネント
npm install lucide-react # アイコン
Phase 1: UIコンポーネント統合(3-4日)
1.1 基本コンポーネント移植
// 抽出対象コンポーネント優先順位
const componentPriority = {
高: ['ProductCard', 'ProductGallery', 'AddToCart', 'Cart'],
中: ['ProductList', 'Search', 'Navigation', 'Footer'],
低: ['UserMenu', 'CustomerForm', 'OrderHistory']
}
// 移植手順
// 1. Next.js Commerce → components/ui/ にコピー
// 2. Shopify依存部分 → BFF API呼び出しに変更
// 3. 認証部分 → Firebase Auth連携に変更
1.2 スタイリング統合
/* tailwind.config.js - 時の絵ガイドライン適用 */
module.exports = {
theme: {
extend: {
colors: {
tokinoe: {
white: '#FFFFFF',
cream: '#F5F3E7',
black: '#111111',
gray: '#6B7280',
accent: '#264653' // 藍
}
},
fontFamily: {
serif: ['Noto Serif JP', 'serif'],
sans: ['Noto Sans JP', 'sans-serif']
}
}
}
}
1.3 型定義統合
// types/product.ts - BFF APIと互換性を持つ型定義
interface Product {
id: string
title: string
description: string
vendor: string // 作家名 (時の絵)
productType: 'neko' | 'tokinoe' // ブランド識別
variants: ProductVariant[]
images: ProductImage[]
metafields?: {
brand: string
firebase_uid: string
technique: string // 技法 (時の絵)
}
}
interface ProductVariant {
id: string
title: string // "プレミアムフレーム・ブラック×ホワイト"
price: number
availableForSale: boolean
image?: ProductImage
}
Phase 2: API統合層(2-3日)
2.1 BFF API アダプター作成
// lib/shopify/adapter.ts - Next.js Commerce → BFF変換
export class ShopifyBFFAdapter {
async getProducts(params: {
collection?: string
brand?: 'neko' | 'tokinoe'
limit?: number
}) {
// BFF API (/api/products) 呼び出し
const response = await fetch('/api/products', {
method: 'POST',
headers: { 'Authorization': `Bearer ${await getFirebaseToken()}` },
body: JSON.stringify(params)
})
// Next.js Commerce形式に変換
const data = await response.json()
return this.transformToCommerceFormat(data)
}
async addToCart(productId: string, variantId: string) {
// BFF経由でShopify Cart API呼び出し
return await this.callBFF('/api/cart/add', {
productId, variantId
})
}
private async callBFF(endpoint: string, data: any) {
return fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getFirebaseToken()}`
},
body: JSON.stringify(data)
})
}
}
2.2 認証統合
// lib/auth/firebase-shopify-bridge.ts
export class FirebaseShopifyBridge {
async getCurrentUser() {
const firebaseUser = await getCurrentUser() // Firebase
if (!firebaseUser) return null
// BFF経由でShopify Customer ID取得
const shopifyCustomer = await this.getShopifyCustomer(firebaseUser.uid)
return {
firebase: firebaseUser,
shopify: shopifyCustomer
}
}
async createCartSession() {
const user = await this.getCurrentUser()
// Firebase UIDとShopify Customer IDの紐付けでカート作成
return await fetch('/api/cart/create', {
headers: { 'Authorization': `Bearer ${await user.firebase.getIdToken()}` }
})
}
}
Phase 3: 統合テスト・最適化(2-3日)
3.1 コンポーネントテスト
// __tests__/components/ProductCard.test.tsx
import { render, screen } from '@testing-library/react'
import { ProductCard } from '@/components/ui/ProductCard'
describe('ProductCard', () => {
const mockProduct = {
id: 'test-product',
title: '紅葉 / 山田太郎',
vendor: '山田太郎',
productType: 'tokinoe'
}
test('時の絵商品の表示', () => {
render(<ProductCard product={mockProduct} />)
expect(screen.getByText('紅葉')).toBeInTheDocument()
expect(screen.getByText('山田太郎')).toBeInTheDocument()
})
})
3.2 パフォーマンス最適化
// components/optimized/ProductGallery.tsx - 画像最適化
import Image from 'next/image'
export function ProductGallery({ images }: { images: ProductImage[] }) {
return (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{images.map((image, index) => (
<Image
key={image.id}
src={image.url}
alt={image.altText}
width={800}
height={600}
priority={index === 0}
className="rounded-lg object-cover"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..." // R2最適化画像
/>
))}
</div>
)
}
🏗️ アーキテクチャ統合パターン
統合後システム構成
graph TB
subgraph "Frontend (Next.js + Commerce UI)"
A1[Next.js App Router]
A2[Commerce UI Components]
A3[Tailwind CSS + shadcn/ui]
end
subgraph "Authentication"
B1[Firebase Auth]
B2[Firebase-Shopify Bridge]
end
subgraph "BFF Layer (Cloudflare Workers)"
C1[API Routes]
C2[Shopify API Integration]
C3[PII Filtering]
C4[Rate Limiting Queue]
end
subgraph "Data Storage"
D1[Shopify - PII Data]
D2[Cloudflare D1 - Non-PII]
D3[Cloudflare R2 - Assets]
end
A1 --> A2
A2 --> B1
B1 --> B2
B2 --> C1
C1 --> C2
C2 --> C3
C3 --> C4
C4 --> D1
C1 --> D2
A2 --> D3
データフロー例(商品表示)
1. ProductPage Component:
- Next.js Commerce UI使用
- getStaticProps / generateStaticParams
2. BFF API Call:
- /api/products/{id} (Workers)
- Firebase認証トークン付き
3. Shopify API:
- Storefront API → 商品情報取得
- Admin API → 在庫・価格(必要に応じて)
4. Data Transform:
- PII分離フィルタリング
- Next.js Commerce形式変換
5. UI Render:
- RSC + Suspense最適化
- 画像はR2 CDN経由
🎨 ブランド別カスタマイズ
時の絵 (TOKINOE) 特化
// components/tokinoe/ProductDisplay.tsx
export function TokinoeProductDisplay({ product }: { product: Product }) {
return (
<div className="max-w-7xl mx-auto px-4 py-8">
{/* 作家・技法表示 */}
<div className="mb-6">
<h1 className="text-3xl font-serif text-tokinoe-black">
{product.title}
</h1>
<p className="text-tokinoe-gray mt-2">
作家: {product.vendor} / 技法: {product.metafields?.technique}
</p>
</div>
{/* 商品ギャラリー */}
<TokinoeProductGallery images={product.images} />
{/* バリアント選択 */}
<TokinoeVariantSelector variants={product.variants} />
{/* 作品解説 */}
<TokinoeArtworkDescription description={product.description} />
</div>
)
}
猫アプリ (NEKO) 特化
// components/neko/PhotoPrintCustomizer.tsx
export function PhotoPrintCustomizer({ product }: { product: Product }) {
return (
<div className="bg-white rounded-xl shadow-lg p-6">
<h2 className="text-2xl font-bold text-gray-800 mb-4">
📸 写真をアップロード
</h2>
{/* ファイルアップロード */}
<PhotoUploadZone onUpload={handlePhotoUpload} />
{/* プレビュー */}
<PhotoPreview images={uploadedPhotos} />
{/* サイズ選択 */}
<NekoSizeSelector sizes={['89mm x 127mm', '102mm x 152mm']} />
</div>
)
}
📊 移行スケジュール・マイルストーン
Week 1: 基盤構築
Day 1: 環境セットアップ・依存関係インストール
Day 2: 基本UIコンポーネント抽出・移植
Day 3: スタイリング統合・テーマ設定
Day 4: 型定義・インターフェース作成
Day 5: 初期統合テスト・動作確認
Week 2: 機能統合
Day 1: BFF APIアダプター実装
Day 2: 認証統合・セッション管理
Day 3: 商品表示・カート機能統合
Day 4: チェックアウトフロー統合
Day 5: E2Eテスト・パフォーマンス最適化
Week 3: 本番準備
Day 1: ブランド別カスタマイズ完成
Day 2: アクセシビリティ・SEO最適化
Day 3: セキュリティ監査・PII分離確認
Day 4: ステージング環境テスト
Day 5: 本番デプロイ・監視設定
🚨 リスク管理・回避策
技術的リスク
Bundle Size増加:
リスク: Cloudflare Workers 10MB制限
対策: Tree-shaking + Dynamic Import
Performance劣化:
リスク: RSC/SSR処理負荷
対策: Static Generation + Edge Caching
既存機能破綻:
リスク: BFF統合時のバグ混入
対策: Feature Flag + AB Testing
運用リスク
開発負荷増:
リスク: チーム学習コスト
対策: 段階的導入 + ドキュメント整備
保守複雑化:
リスク: 技術スタック多様化
対策: 共通コンポーネント化 + TypeScript型安全
コスト増加:
リスク: 追加開発・テスト工数
対策: ROI監視 + 最小限統合
✅ 成功指標・KPI
技術指標
パフォーマンス:
- Lighthouse Score: 95+ (現在85)
- Core Web Vitals: Good範囲維持
- Bundle Size: 制限内収束
開発効率:
- コンポーネント再利用率: 80%+
- TypeScript型カバレッジ: 90%+
- テストカバレッジ: 85%+
ビジネス指標
UX改善:
- コンバージョン率: +15-25%
- 離脱率: -20%
- カート放棄率: -15%
運用効率:
- 開発速度: +30%
- バグ修正時間: -40%
- 新機能リリース頻度: +50%
📍 実装開始の判断基準
✅ GO判定条件
- 開発リソース確保(1-2週間集中)
- ステージング環境準備完了
- BFF API安定性確認
- デザインガイドライン確定
❌ STOP判定条件
- 既存システム不安定要素発見
- Cloudflare Workers制限抵触
- 開発工数が予算50万円超過
- パフォーマンス劣化確認
📍 関連ドキュメント: 概要 | コンポーネント設計 | パフォーマンス最適化
文書作成日: 2025-08-23
最終更新: 2025-08-23
バージョン: 1.0 - 実装戦略版