こんにちは!前回のエピソードでは、Next.jsプロジェクトの環境をセットアップし、TypeScript、Tailwind CSS、ESLint、Prettierを統合しました。シリーズ2回目となる今回は、ヘッドレスコマースプラットフォーム(Shopify Storefront API)をNext.jsに統合し、商品一覧ページ(PLP: Product Listing Page)を構築します。APIクライアントの設定やデータの取得方法についても詳しく解説します!
このエピソードのゴール
- Shopify Storefront APIをNext.jsに接続する。
- 商品データを取得して表示するAPIクライアントを作成。
-
getStaticProps
を使って商品一覧ページを構築。 - Tailwind CSSでレスポンシブな商品リストUIをデザイン。
必要なもの
- 前回のプロジェクト(
next-ecommerce
)がセットアップ済み。 - Shopifyストア(またはテスト用の無料ストア)。
- Shopify Storefront APIのアクセストークン。
- 基本的なTypeScriptとReactの知識。
ステップ1: Shopify Storefront APIの準備
Shopify Storefront APIは、ヘッドレスコマースで商品データやカート情報を取得するためのGraphQL APIです。以下の手順で準備します:
-
Shopifyストアの設定:
- Shopifyアカウントを作成(無料トライアル可)。
- テスト用の商品をいくつか追加(例: Tシャツ、ジャケットなど)。
-
Storefront APIの有効化:
- Shopify管理画面で「アプリとセールスチャネル」→「アプリを開発」を選択。
- 新しいアプリを作成し、「Storefront API」を有効化。
- アクセストークンを取得(後で使用)。
-
GraphQLエンドポイント:
- エンドポイントは通常
https://あなたのストア.myshopify.com/api/2024-10/graphql.json
の形式。
- エンドポイントは通常
ステップ2: APIクライアントの作成
Shopify Storefront APIと通信するために、GraphQLクライアントをセットアップします。graphql-request
ライブラリを使用します。
ライブラリのインストール
ターミナルで以下のコマンドを実行:
npm install graphql-request
APIクライアントの実装
src/lib/shopify.ts
ファイルを作成し、以下のコードを追加:
import { GraphQLClient } from 'graphql-request';
const endpoint = 'https://あなたのストア.myshopify.com/api/2024-10/graphql.json';
const storefrontAccessToken = 'あなたのアクセストークン';
export const shopifyClient = new GraphQLClient(endpoint, {
headers: {
'X-Shopify-Storefront-Access-Token': storefrontAccessToken,
},
});
注意: アクセストークンは機密情報です。本番環境では.env
ファイルを使って管理します。.env.local
に以下を追加:
NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN=あなたのアクセストークン
NEXT_PUBLIC_SHOPIFY_STOREFRONT_ENDPOINT=https://あなたのストア.myshopify.com/api/2024-10/graphql.json
その後、src/lib/shopify.ts
を以下のように修正:
import { GraphQLClient } from 'graphql-request';
const endpoint = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ENDPOINT!;
const storefrontAccessToken = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN!;
export const shopifyClient = new GraphQLClient(endpoint, {
headers: {
'X-Shopify-Storefront-Access-Token': storefrontAccessToken,
},
});
ステップ3: 商品データを取得するクエリ
商品一覧を取得するためのGraphQLクエリを作成します。src/lib/queries.ts
ファイルを作成し、以下のクエリを追加:
export const GET_PRODUCTS_QUERY = `
query GetProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
title
handle
priceRange {
minVariantPrice {
amount
currencyCode
}
}
images(first: 1) {
edges {
node {
url
altText
}
}
}
}
}
}
}
`;
このクエリは、商品のID、タイトル、URLハンドル、価格、画像を取得します。
次に、商品データを取得する関数をsrc/lib/shopify.ts
に追加:
import { GraphQLClient } from 'graphql-request';
import { GET_PRODUCTS_QUERY } from './queries';
const endpoint = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ENDPOINT!;
const storefrontAccessToken = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN!;
export const shopifyClient = new GraphQLClient(endpoint, {
headers: {
'X-Shopify-Storefront-Access-Token': storefrontAccessToken,
},
});
interface Product {
id: string;
title: string;
handle: string;
priceRange: {
minVariantPrice: {
amount: string;
currencyCode: string;
};
};
images: {
edges: Array<{
node: {
url: string;
altText: string | null;
};
}>;
};
}
interface ProductsResponse {
products: {
edges: Array<{ node: Product }>;
};
}
export async function getProducts(first: number): Promise<Product[]> {
const data = await shopifyClient.request<ProductsResponse>(GET_PRODUCTS_QUERY, { first });
return data.products.edges.map((edge) => edge.node);
}
この関数は、指定した数の商品データを取得し、型安全な形で返します。
ステップ4: 商品一覧ページの構築
src/app/page.tsx
を更新して、商品一覧を表示します。getStaticProps
を使用してビルド時にデータを取得します:
import { getProducts } from '@/lib/shopify';
import Link from 'next/link';
interface Product {
id: string;
title: string;
handle: string;
priceRange: {
minVariantPrice: {
amount: string;
currencyCode: string;
};
};
images: {
edges: Array<{
node: {
url: string;
altText: string | null;
};
}>;
};
}
interface HomeProps {
products: Product[];
}
export async function getStaticProps() {
const products = await getProducts(10); // 最初の10商品を取得
return {
props: {
products,
},
revalidate: 60, // ISR: 60秒ごとに再生成
};
}
export default function Home({ products }: HomeProps) {
return (
<main className="container mx-auto p-4">
<h1 className="text-3xl font-bold mb-6">商品一覧</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
{products.map((product) => (
<Link href={`/products/${product.handle}`} key={product.id}>
<div className="border rounded-lg p-4 hover:shadow-lg transition">
<img
src={product.images.edges[0]?.node.url}
alt={product.images.edges[0]?.node.altText || product.title}
className="w-full h-48 object-cover rounded"
/>
<h2 className="text-xl font-semibold mt-2">{product.title}</h2>
<p className="text-gray-600">
{parseFloat(product.priceRange.minVariantPrice.amount).toFixed(2)}{' '}
{product.priceRange.minVariantPrice.currencyCode}
</p>
</div>
</Link>
))}
</div>
</main>
);
}
このコードは:
-
getStaticProps
で商品データを取得(ISRを有効化)。 - Tailwind CSSを使ってレスポンシブなグリッドレイアウトを作成。
- 各商品をカード形式で表示し、クリックすると商品詳細ページに遷移(後で実装)。
ステップ5: 動作確認
-
.env.local
にShopifyのエンドポイントとアクセストークンを設定。 - 開発サーバーを起動(
npm run dev
)。 -
http://localhost:3000
にアクセスし、商品一覧が表示されるか確認。
商品カードがグリッド形式で表示され、画像、タイトル、価格が正しく表示されていれば成功です。エラーがあれば、コンソールやShopifyのアクセストークンを確認してください。
まとめと次のステップ
このエピソードでは、Shopify Storefront APIをNext.jsに統合し、商品一覧ページを構築しました。graphql-request
を使ったAPIクライアントの設定や、getStaticProps
によるデータ取得の方法を学びました。Tailwind CSSのおかげで、レスポンシブでモダンなUIも簡単に実現できました!
次回のエピソードでは、商品詳細ページ(PDP)を構築し、SEO最適化や画像の遅延読み込みを追加します。動的ルーティングやメタタグの設定も詳しく解説しますので、ぜひお楽しみに!
この記事が役に立ったと思ったら、ぜひ「いいね」を押して、ストックしていただければ嬉しいです!次回のエピソードもお楽しみに!