Nuxt3を使ってShopifyの商品一覧を取得しよう
  • 2022.03.09に公開
  • 2022.03.14に更新
  • Nuxt3
  • 1. Shopify APIとの連携
  • No.1 / 5
このカテゴリーは、Nuxt3パブリックベータ版の情報を公開しています。最新の情報は Nuxt3の公式サイト をご確認ください。

この記事で達成すること

ECサイト「Shopify」のコンテンツをNuxt3で表示します。

2022-03-09 20-16-13

なお、

は各リンクを参照し済ませておいてください。

Shopifyの料金

Shopifyは月$29の料金が発生しますが、14日間のお試し期間が設けられています。

14日以内にストアを削除すれば料金はかかりません。

参考: Shopify Pricing

Shopifyに商品を登録する

Shopifyにログイン後、複数のデモ商品を登録します。

2022-03-09 18-54-24

Shopifyのアクセストークンを発行する

Shopifyの商品データにアクセスするためにストアフロントアクセストークンを使用します。

アクセストークンを発行するには、Shopifyの管理画面上でアプリを作成します。

「アプリを作成」 => 「アプリを開発」

2022-03-09 18-59-00

「アプリを作成」

2022-03-09 19-00-51

アプリ名を入力 => 「アプリを作成」

2022-03-09 19-04-08

「ストアフロントAPIスコープを設定する」

2022-03-09 19-08-44

許可するスコープにチェック => 「保存」

開発環境上では全てにチェックを入れておけばOKです。

それぞれのスコープの説明は下記リンクを参照してください。

Shopify API Access scopes

2022-03-09 19-10-32

「アプリをインストール」

2022-03-09 19-15-46

「API資格情報」 => 「クリップボードにコピー」

2022-03-09 19-17-02

これでストアフロントアクセストークンが発行できました。

Nxutの.envファイルにトークンを保存する

Nuxtプロジェクト直下に.envファイルを作成します。

$ touch .env

作成した.envファイルに

  • Shopifyのストアドメインと
  • ストアフロントアクセストークン

を追加します。

.env
SHOPIFY_DOMAIN=<ストアドメイン>.myshopify.com
SHOPIFY_ACCESS_TOKEN=<ストアフロントアクセストークン>

nuxt-shopifyのインストールとセットアップ

NuxtからShopifyへAPIを投げるにはnuxt-shopifyモジュールを使用します。

インストールしましょう。

% yarn add nuxt-shopify

nuxt-shopifyの型を登録します。

tsconfig.json
{
  // https://v3.nuxtjs.org/concepts/typescript
  "extends": "./.nuxt/tsconfig.json",
  "compilerOptions": {
    "types": [
      "nuxt-shopify"
    ]
  }
}

nuxt-shopifyのセットアップはnuxt.config.ts

  • ドメイン
  • ストアフロントアクセストークン
  • unoptimizedオプション(コメント参照)
  • ショップの言語

を指定するだけでOKです。

nuxt.config.ts
import { defineNuxtConfig } from 'nuxt3'

// https://v3.nuxtjs.org/docs/directory-structure/nuxt.config
export default defineNuxtConfig({
  modules: [
    'nuxt-shopify'
  ],

  // Doc: https://nuxt-shopify-docs.vercel.app/
  shopify: {
    // shopify domain
    domain: process.env.SHOPIFY_DOMAIN,

    /*
      ストアフロントアクセストークン
    */
    storefrontAccessToken: process.env.SHOPIFY_ACCESS_TOKEN,

    /*
      unoptimized: true => SDKの拡張
      StorefrontAPIで使用できるすべてのフィールドがSDKを介して公開されるわけではありません。
      最適化されていないバージョンのSDKを使用すると、独自のクエリを簡単に作成できます。
      これを行うには、UMDUnoptimizedビルドを使用します。
      Doc: https://shopify.github.io/js-buy-sdk/
    */
    unoptimized: false,

    // 翻訳されたコンテンツを返すための言語を設定する
    language: 'ja-JP',
  }
})

これでnuxt-shopifyのセットアップは完了です。

app.vueにページファイル読み込み設定を行う

作成時点のNuxt3はページファイルを読み込みません。

ページファイルを読み込むためには、app.vue<NuxtPage />コンポーネントを使用します。

app.vue
<template>
  <div>
    <!-- 書き換え -->
    <NuxtPage />
    <!-- <NuxtWelcome /> -->
  </div>
</template>

<NuxtPage />を使用することでpagesディレクトリ以下のファイルを読み込むようになります。

レイアウトファイルを作成する

今後の利便性を考え、レイアウトファイルを作成します。

Nuxt3のレイアウトファイルの使い方は下記記事をご覧ください。

Nuxt3でレイアウトファイルを使用するにはNuxtLayoutを使う

% mkdir layouts && touch $_/default.vue

default.vueにはホームに戻るリンクを追加します。

layouts/default.vue
<template>
  <div>
    <div>
      <NuxtLink
        to="/"
      >
        Home
      </NuxtLink>
    </div>

    <!-- pagesの呼び出し -->
    <slot />
  </div>
</template>

トップページを作成する

http://localhost:3000に表示されるトップページを作成します。

% mkdir pages && touch $_/index.vue

トップページには各リンクを設置します。

pages/index.vue
<template>
  <NuxtLayout>
    <div
      v-for="(page, i) in pages"
      :key="`page-${i}`"
    >
      <NuxtLink
        :to="page.name"
      >
        {{ page.name }}
      </NuxtLink>
    </div>
  </NuxtLayout>
</template>

<script setup lang="ts">
  const pages = [
    { name: '/products' }
  ]
</script>

まだリンク先を生成していないのでルートエラーが発生すると思います。

この先解決しますので次へ進んでください。

商品一覧ページとコンテンツページを作成する

Shopifyから取得した

  • 商品一覧を表示するページ(products/index.vue)と
  • 商品のコンテンツページ(products/[id].vue)を
  • 「pages/products」ディレクトリ以下に作成します。

必要なディレクトリとページファイルを作成します。

mkdir pages/products && touch $_/{index.vue,'[id].vue'}

Nuxt3の動的ルーティングページファイルの作り方は下記記事をご覧ください。

Nuxt3で動的ルーティングを生成するには[id].vueを作成する

現在の「pages」ディレクトリは以下のようになっています。

pages
├── index.vue
└── products
    ├── [id].vue
    └── index.vue

以上でNuxtの下準備は完了です。

現在のトップページ

現在のトップページには、

  • layouts/default.vueで指定したHomeのリンクと
  • pages/index.vueで指定した/productsのリンクが

表示されています。

2022-03-09 20-05-49

Shopifyから商品一覧を取得する

さて、ここからが本番です。

商品一覧ページ(products/index.vue)から商品一覧を取得しましょう。

nuxt-shopifyモジュールにアクセスするには?

nuxt-shopifyモジュールはNuxt2のinject関数が使用されています。

呼び出すにはNuxtインスタンスの$shopifyを使用します。

setup内でNuxtインスタンスにアクセスするにはuseNuxtApp()を使用します。

useNuxtApp()の詳細は下記記事をご覧ください。

Nuxt3のsetup内ではthisの代わりにuseNuxtApp()を使用する

pages/products/index.vue
<script setup lang="ts">
  /* 
    useNuxtApp(): nuxt context(this)へのアクセス
    Nuxt2でinjectされた$appにアクセス可能
    参考: https://blog.logrocket.com/whats-new-nuxt-3/
  */
  const nuxtApp = useNuxtApp()
  // fetchAll()はPromiseが返ってくるためawaitを付け、戻り値を取得する
  const products = await nuxtApp.$shopify.product.fetchAll()
</script>
  • $shopify.product.fetchAll() ... アクティブな商品一覧を取得するnuxt-shopifyのメソッド。Promiseが返るのでawaitを付与する。

    参考: Store actions - Nuxt Shopify

HTMLには各プロパティの値を表示する

<template>タグ内は取得したデータの値を全て表示します。

ここから商品単価や商品画像を選定して表示します。

pages/products/index.vue
<template>
  <NuxtLayout>
    <ul
      v-for="(product, i) in products"
      :key="`product-${i}`"
    >
      <li>
        <NuxtLink
          :to="{ name: 'products-id', params: { id: product.id } }"
        >
          {{ product.title }}
        </NuxtLink>

        <ul
          v-for="(key, keyI) in Object.keys(product)"
          :key="`key-${keyI}`"
        >
          <li v-if="key === 'images'">
            {{ key }}:
            <ol>
              <li
                v-for="(image, imageI) in product['images']"
                :key="`image-${imageI}`"
              >
                <ul
                  v-for="(imageKey, imageKeyI) in Object.keys(image)"
                  :key="`imageKey-${imageKeyI}`"
                >
                  <li>
                    {{ imageKey }}:
                    {{ image[imageKey] }}
                  </li>
                </ul>
              </li>
            </ol>  
          </li>

          <li v-else-if="key === 'variants'">
            {{ key }}:
            <ol>
              <li
                v-for="(variant, variantI) in product['variants']"
                :key="`variant-${variantI}`"
              >
                <ul
                  v-for="(variantKey, variantKeyI) in Object.keys(variant)"
                  :key="`variantKey-${variantKeyI}`"
                >
                  <li>
                    {{ variantKey }}:
                    {{ variant[variantKey] }}
                  </li>
                </ul>
              </li>
            </ol>  
          </li>

          <li v-else>  
            {{ key }}:
            {{ product[key] }}
          </li>
        </ul>
      </li>
    </ul>
  </NuxtLayout>
</template>

ShopifyAPIのfetchAll()で取得できるプロパティ抜粋

  • id ... 商品固有のID。このIDから特定の商品を取得する
  • descriptionHtml ... 商品の説明HTMLバージョン
  • description .. 商品の説明
  • title ... 商品名
  • images: [] ... 商品画像の配列
    • src ... 画像URL
    • width ... 画像幅
    • height ... 画像高さ
  • variants: [] ... 価格情報の配列
    • price ... 商品単価

在庫数や重量などは取得できませんでした。

商品一覧ページを確認しよう

商品一覧ページにアクセスしてみましょう。

アクティブな商品の情報が大量に表示されています。

2022-03-09 20-16-13

注意!! コンテンツが取得できない場合

過去、APIリクエストとレスポンスにエラーが無いのに商品が取得できない現象がありました。

これは商品が下書き状態でアクセストークンを発行した場合に発生しました。

同じ現象に遭遇した方は、上記Shopifyのアクセストークンを発行するを実行し、ストアフロントアクセストークンを再発行してください。

筆者はトークンを入れ替えることでエラー回避ができました。

商品コンテンツページを作成しよう

商品コンテンツを取得するには、$shopify.product.fetch(<商品ID>)を使用します。

商品IDはroute.params.idに格納されています。

setup内でNuxtのrouteを取得するには、useRoute()を使用します。

pages/products/[id].vue
<script setup lang="ts">
  const nuxtApp = useNuxtApp()
  const route = useRoute()

  const product = await nuxtApp.$shopify.product.fetch(route.params.id)
</script>

HTMLは商品一覧ページと同じで書くプロパティの値を表示しておきましょう。

pages/products/[id].vue
<template>
  <NuxtLayout>
    <NuxtLink
      to="/products"
    >
      products
    </NuxtLink>
    <ul
      v-for="(key, keyI) in Object.keys(product)"
      :key="`key-${keyI}`"
    >
      <li v-if="key === 'images'">
        {{ key }}:
        <ol>
          <li
            v-for="(image, imageI) in product['images']"
            :key="`image-${imageI}`"
          >
            <ul
              v-for="(imageKey, imageKeyI) in Object.keys(image)"
              :key="`imageKey-${imageKeyI}`"
            >
              <li>
                {{ imageKey }}:
                {{ image[imageKey] }}
              </li>
            </ul>
          </li>
        </ol>  
      </li>

      <li v-else-if="key === 'variants'">
        {{ key }}:
        <ol>
          <li
            v-for="(variant, variantI) in product['variants']"
            :key="`variant-${variantI}`"
          >
            <ul
              v-for="(variantKey, variantKeyI) in Object.keys(variant)"
              :key="`variantKey-${variantKeyI}`"
            >
              <li>
                {{ variantKey }}:
                {{ variant[variantKey] }}
              </li>
            </ul>
          </li>
        </ol>  
      </li>

      <li v-else>  
        {{ key }}:
        {{ product[key] }}
      </li>
    </ul>
  </NuxtLayout>
</template>

パラメーターIDのコンテンツが取得できました。

2022-03-09 20-39-47

今回の作業は以上です。

まとめ

今回はNuxt3からShopifyに登録した商品一覧をAPIで取得する設定を行いました。

これをうまく使用すると、商品管理、決済はShopifyに任せ、商品ページはNuxtで構築することができます。

いわゆるヘッドレスECサイトですね。


ここで紹介した技術は最初の最初の1歩ですが、ここからNuxt × ECサイトの可能性が広がりそうです。

また新しい情報を取得したらここで紹介しますね。お楽しみに。

あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
独学プログラマ
独学でも、ここまでできるってよ。
CONTACT
Nuxt.js制作のご依頼は下記メールアドレスまでお送りください。