PortfolioCMS領域を専門としたWeb Developer & Director

Shopify Storefront Web Components 実践レポート:第2回

前置き

以下の構成で検証を進めています。

  • ECカート:Shopify Storefront Web Components
  • フレームワーク:Astro
  • 記事管理:microCMS

調査の背景

2025年の夏に発表されたShopify Storefront Web Componentsを活用すると、Shopify以外のサイトにも手軽にEC機能を組み込めるようになります。

仕組みとしてはヘッドレスCMSに近いですが、従来のようにAPIを直接叩いて独自ロジックを組む必要がありません。コンポーネントを配置するだけで、複雑なAPI処理を意識せずにEC機能を導入できる点が大きな特徴です。

記事執筆時点ではまだ未知の部分もありますが、たとえばWordPressで管理している記事コンテンツを組み合わせるなど、今後の外部連携で活用できる可能性を感じており、検証を進めています。

今週の調査内容

コレクションページの実装

コレクションページの実装ポイントは、大きく「動的ルーティング(URL の発行)」と「フロントへのコレクション描画」「ページネーション」の3点かと思います。

動的ルーティング(URL の発行)

トップページでは <shopify-context type="collection" handle="ハンドル名"> でコレクション情報を取得し、<a shopify-attr--href="'/collections/' + collection.handle"> でコレクションのハンドル名をリンク URLにバインドしています。

<shopify-context type="collection" handle="ハンドル名">
 <template>
  <li>
   <a shopify-attr--href="'/collections/' + collection.handle">
     <figure><shopify-media query="collection.image" width="800" height="800"></shopify-media></figure>
     <h3><shopify-data query="collection.title"></shopify-data></h3>
    </a>
   </li>
 </template>
</shopify-context>

動的ルーティング(URL の発行)

受け取り側は Astro のファイルベースルーティング機能を使い、src/pages/collections/[handle].astro というファイルを用意します。

<shopify-context type="collection" handle={Astro.params.handle}>
 <template>
  <!-- コレクション名や説明文、コレクションに属する商品を取得する記述を追加-->
 </template>
</shopify-context>

これによりユーザーが /collections/ハンドル名 にアクセスすると、そのファイルが読み込まれ、Astro.params.handle にハンドル名がセットされます。

※参考コードは「shopify-store」など一部割愛しておりますのでご注意ください

ページネーションについて

確認した限り、Shopify Storefront Web Components では、ページネーション機能として数字リンク(「1」「2」「3」…)によるページ選択は提供されておらず、標準では「前へ」「次へ」のボタンを使ったカーソルベースの切り替え方式のみが用意されていました。

<shopify-list-context
  id="product-list"
  type="product"
  query="collection.products"
  first="3"
>
  <template>
    <div class="product-card">
      <!-- shopify-media/shopify-data/shopify-money で商品情報を表示 -->
    </div>
  </template>
</shopify-list-context>

first で1ページあたり取得件数を指定。
id はスクリプトから要素を一意に参照するために必須

<div id="pagination">
  <button
    id="prevBtn"
    onclick="document.getElementById('product-list').previousPage()"
    disabled
  >前へ</button>
  <button
    id="nextBtn"
    onclick="document.getElementById('product-list').nextPage()"
    disabled
  >次へ</button>
</div>

初期状態は両ボタンともdisabled。
ボタンのクリックで組み込みメソッド previousPage()/nextPage() を呼び出し

<script>
  // Listen for the list context to update
  // and disable the next and previous buttons when 
  // the list is at the end or beginning
  document
    .querySelector("shopify-context")
    .addEventListener(
      "shopify-list-context-update",
      (event) => {
        const {
          hasNextPage,
          hasPreviousPage,
        } = event.detail;
        if (!hasNextPage) {
          document
            .getElementById("next")
            .setAttribute(
              "disabled",
              "true",
            );
        } else {
          document
            .getElementById("next")
            .removeAttribute("disabled");
        }
        if (!hasPreviousPage) {
          document
            .getElementById("previous")
            ?.setAttribute(
              "disabled",
              "true",
            );
        } else {
          document
            .getElementById("previous")
            .removeAttribute("disabled");
        }
      },
    );
</script>

<shopify-context>(または <shopify-list-context>)の更新イベントを監視し、hasNextPage/hasPreviousPage の真偽に応じて「次へ」「前へ」ボタンに disabled 属性を付け外しを実施。これにより、最初のページでは「前へ」、最後のページでは「次へ」が自動で無効化されます。
公式のMDドキュメント参照

次回の展望

次回は、ホスティングサービスの選定や、静的サイト生成(SSG)とサーバーサイドレンダリング(SSR)といったレンダリング手法の違い・メリットを踏まえながら、実際の運用に最適な構成を検討してみようと思います。

#
執筆者 | 西條輝(Saijo)
Web Developer & Director (EC)
この記事が少しでも役に立ったらフォローいただけると嬉しいです。
X(Twitter)

Related Blog