0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

電子商取引システムの構築と最適化 | 第5部: パフォーマンスとSEOの最適化

Posted at

はじめに

ヘッドレスE-commerceでは、パフォーマンスSEO(検索エンジン最適化)がユーザー体験(UX)とコンバージョン率を大きく左右します。高速なページ読み込みと検索エンジンでの高い可視性は、競争力のあるオンラインストアに不可欠です。この第5部では、Next.jsのServer-Side Rendering (SSR)Incremental Static Regeneration (ISR)、およびVercel Edge Networkを活用してパフォーマンスを最適化し、Shopify Storefront APIのメタデータを用いてSEOを強化する方法を解説します。開発者向けに、Lighthouseスコアの改善、画像最適化、および構造化データの実装に焦点を当てたコードスニペットを提供します。

パフォーマンス最適化の重要性

E-commerceのパフォーマンスは以下の理由で重要です:

  • ユーザー体験: ページ読み込み時間が1秒増加するごとに、コンバージョン率が最大7%低下(Google研究)。
  • SEO: GoogleはCore Web Vitals(LCP、FID、CLS)をランキング要因に使用。
  • スケーラビリティ: 高トラフィック時の安定性を確保。
  • コスト効率: サーバーリソースの最適化で運用コストを削減。

Next.jsVercelは、パフォーマンス向上のための強力なツールを提供します。

パフォーマンス最適化の実装

1. Next.jsのレンダリング戦略

Next.jsISRSSRを活用して、ページ読み込みを高速化します。

ISRの最適化

**Incremental Static Regeneration(ISR)**は、静的ページを生成しつつ、定期的に更新します。第3部で実装した商品ページをさらに最適化:

// pages/products/[handle].tsx (抜粋)
export const getStaticProps: GetStaticProps = async ({ params }) => {
  const { data } = await client.query({
    query: GET_PRODUCT,
    variables: { handle: params?.handle },
  });

  return {
    props: { product: data.product },
    revalidate: 60, // 60秒ごとに再生成
  };
};

ISRの再生成間隔をトラフィックとデータ更新頻度に応じて調整(例:低トラフィックなら300秒)。以下はキャッシュ戦略の強化:

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/products/:handle',
        headers: [
          {
            key: 'Cache-Control',
            value: 'public, max-age=60, stale-while-revalidate=300',
          },
        ],
      },
    ];
  },
};

この設定は、Vercel Edge Networkでキャッシュを活用し、stale-while-revalidateで古いコンテンツを再生成中に提供します。

SSRの使用

動的データ(例:リアルタイム在庫)が必要な場合、SSRを適用:

// pages/inventory/[id].tsx
import { GetServerSideProps } from 'next';
import { gql } from '@apollo/client';
import { client } from '../../lib/apollo-client';

const GET_INVENTORY = gql`
  query GetInventory($id: ID!) {
    product(id: $id) {
      id
      variants(first: 10) {
        edges {
          node {
            id
            inventoryQuantity
          }
        }
      }
    }
  }
`;

export const getServerSideProps: GetServerSideProps = async ({ params }) => {
  const { data } = await client.query({
    query: GET_INVENTORY,
    variables: { id: params?.id },
  });

  return {
    props: { product: data.product },
  };
};

export default function InventoryPage({ product }: { product: any }) {
  return (
    <div className="container mx-auto p-4">
      <h1 className="text-3xl font-bold mb-6">在庫状況</h1>
      {product.variants.edges.map(({ node }: { node: any }) => (
        <p key={node.id}>バリエーションID: {node.id} - 在庫: {node.inventoryQuantity}</p>
      ))}
    </div>
  );
}

SSRはリアルタイム性が求められるページに適していますが、サーバーリソースを考慮して使用します。

2. 画像最適化

Next.js Imageで画像を自動圧縮し、WebP形式を優先:

// components/ProductCard.tsx (抜粋)
import Image from 'next/image';

<Image
  src={product.images.edges[0]?.node.src}
  alt={product.images.edges[0]?.node.altText || product.title}
  fill
  className="object-cover rounded"
  sizes="(max-width: 768px) 100vw, 33vw"
  quality={75} // 品質を調整(デフォルト: 75)
  priority={index === 0} // 最初の画像は優先ロード
/>

Vercel Image Optimizationを有効化(next.config.js):

module.exports = {
  images: {
    domains: ['cdn.shopify.com'],
    formats: ['image/webp'],
    minimumCacheTTL: 3600, // キャッシュ期間1時間
  },
};

これにより、画像の読み込み時間が短縮され、**Largest Contentful Paint(LCP)**が改善されます。

3. コード分割と遅延読み込み

Next.jsdynamic importでコンポーネントを遅延読み込み:

// pages/index.tsx (抜粋)
import dynamic from 'next/dynamic';

const ProductList = dynamic(() => import('../components/ProductList'), {
  ssr: false, // クライアントサイドでのみレンダリング
  loading: () => <p>Loading...</p>,
});

これにより、初回ロード時のJavaScriptバンドルサイズを削減します。

SEO最適化

SEOはトラフィックとコンバージョンを増やすために不可欠です。Shopify Storefront APIのメタデータを利用してSEOを強化します。

1. メタタグの動的設定

商品ページでメタタグOpen Graphデータを設定:

// pages/products/[handle].tsx (抜粋)
import Head from 'next/head';

export default function ProductPage({ product }: { product: any }) {
  const description = product.description.slice(0, 160);
  const image = product.images.edges[0]?.node.src;

  return (
    <>
      <Head>
        <title>{`${product.title} | YourStore`}</title>
        <meta name="description" content={description} />
        <meta name="keywords" content={`${product.title}, e-commerce, shopify`} />
        <meta property="og:title" content={product.title} />
        <meta property="og:description" content={description} />
        <meta property="og:image" content={image} />
        <meta property="og:type" content="product" />
        <link rel="canonical" href={`https://my-ecommerce.vercel.app/products/${product.handle}`} />
      </Head>
      {/* 残りのコード */}
    </>
  );
}

2. 構造化データの追加

JSON-LDで商品データを構造化し、Googleのリッチリザルトをサポート:

// pages/products/[handle].tsx (抜粋)
<Head>
  <script type="application/ld+json">
    {JSON.stringify({
      "@context": "https://schema.org",
      "@type": "Product",
      name: product.title,
      image: product.images.edges[0]?.node.src,
      description: product.description.slice(0, 160),
      offers: {
        "@type": "Offer",
        priceCurrency: product.priceRange.minVariantPrice.currencyCode,
        price: product.priceRange.minVariantPrice.amount,
        availability: "https://schema.org/InStock",
      },
    })}
  </script>
</Head>

3. サイトマップの生成

動的サイトマップを生成して、検索エンジンにページを通知:

// pages/sitemap.xml.tsx
import { GetServerSideProps } from 'next';
import { gql } from '@apollo/client';
import { client } from '../lib/apollo-client';

const GET_ALL_PRODUCTS_AND_COLLECTIONS = gql`
  query GetAllProductsAndCollections {
    products(first: 100) { edges { node { handle } } }
    collections(first: 100) { edges { node { handle } } }
  }
`;

export const getServerSideProps: GetServerSideProps = async ({ res }) => {
  const { data } = await client.query({ query: GET_ALL_PRODUCTS_AND_COLLECTIONS });

  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
      <url><loc>https://my-ecommerce.vercel.app/</loc></url>
      ${data.products.edges
        .map(({ node }: { node: any }) => `<url><loc>https://my-ecommerce.vercel.app/products/${node.handle}</loc></url>`)
        .join('')}
      ${data.collections.edges
        .map(({ node }: { node: any }) => `<url><loc>https://my-ecommerce.vercel.app/collections/${node.handle}</loc></url>`)
        .join('')}
    </urlset>`;

  res.setHeader('Content-Type', 'text/xml');
  res.write(sitemap);
  res.end();

  return { props: {} };
};

export default function Sitemap() {
  return null;
}

Google Search Consoleでサイトマップを送信:

# Search Consoleでのサイトマップ送信
1. Google Search Consoleにアクセス
2. プロパティを追加(https://my-ecommerce.vercel.app)
3. サイトマップ(/sitemap.xml)を送信

Vercel Edge Networkの活用

VercelEdge Networkを活用して、グローバルなパフォーマンスを向上:

# Vercelでのキャッシュ設定
1. Vercelダッシュボードにログイン
2. 「Project Settings」→「Edge Config」を有効化
3. キャッシュポリシーを設定:
   - Cache-Control: public, max-age=60, stale-while-revalidate=300
4. グローバルCDNを活用(自動有効)

パフォーマンステストとデバッグ

以下のテストを実施:

  • Lighthouseテスト: スコア90以上を目指す(Performance, SEO, Accessibility)。
  • Core Web Vitals: LCP(2.5秒以下)、FID(100ms以下)、CLS(0.1以下)。
  • キャッシュテスト: ページが正しくキャッシュされるか。
  • SEOテスト: Google Search Consoleでインデックス状況を確認。

Lighthouse CLIの実行:

npm install -g lighthouse
lighthouse https://my-ecommerce.vercel.app --output html --output-path report.html

まとめ

この第5部では、Next.jsVercelを使ったパフォーマンスSEOの最適化を解説しました。ISR画像最適化構造化データ、およびEdgeキャッシュにより、高速で検索エンジンに最適化されたE-commerceを構築しました。次の第6部では、セキュリティデータ管理について掘り下げます。

Qiitaの皆さん、この記事が役に立ったら「いいね」や「ストック」をお願いします!コメントで技術的な質問や提案もお待ちしています!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?