この記事で達成すること
ECサイト「Shopify」のコンテンツをNuxt3で表示します。
なお、
- Shopifyへの会員登録
- ストアのドメイン登録
- Nuxt3の立ち上げ
は各リンクを参照し済ませておいてください。
Shopifyの料金
Shopifyは月$29の料金が発生しますが、14日間のお試し期間が設けられています。
14日以内にストアを削除すれば料金はかかりません。
参考: Shopify Pricing
Shopifyに商品を登録する
Shopifyにログイン後、複数のデモ商品を登録します。
Shopifyのアクセストークンを発行する
Shopifyの商品データにアクセスするためにストアフロントアクセストークンを使用します。
アクセストークンを発行するには、Shopifyの管理画面上でアプリを作成します。
「アプリを作成」 => 「アプリを開発」
「アプリを作成」
アプリ名を入力 => 「アプリを作成」
「ストアフロントAPIスコープを設定する」
許可するスコープにチェック => 「保存」
開発環境上では全てにチェックを入れておけばOKです。
それぞれのスコープの説明は下記リンクを参照してください。
「アプリをインストール」
「API資格情報」 => 「クリップボードにコピー」
これでストアフロントアクセストークンが発行できました。
Nxutの.envファイルにトークンを保存する
Nuxtプロジェクト直下に
$ touch .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
のセットアップは
- ドメイン
- ストアフロントアクセストークン
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はページファイルを読み込みません。
ページファイルを読み込むためには、<NuxtPage />
コンポーネントを使用します。
app.vue
<template>
<div>
<!-- 書き換え -->
<NuxtPage />
<!-- <NuxtWelcome /> -->
</div>
</template>
<NuxtPage />
を使用することで「pages」ディレクトリ以下のファイルを読み込むようになります。
レイアウトファイルを作成する
今後の利便性を考え、レイアウトファイルを作成します。
Nuxt3のレイアウトファイルの使い方は下記記事をご覧ください。
% mkdir layouts && touch $_/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の動的ルーティングページファイルの作り方は下記記事をご覧ください。
現在の「pages」ディレクトリは以下のようになっています。
pages
├── index.vue
└── products
├── [id].vue
└── index.vue
以上でNuxtの下準備は完了です。
現在のトップページ
現在のトップページには、
layouts/default.vue で指定したHome
のリンクとpages/index.vue で指定した/products
のリンクが
表示されています。
Shopifyから商品一覧を取得する
さて、ここからが本番です。
商品一覧ページ(
nuxt-shopifyモジュールにアクセスするには?
nuxt-shopify
モジュールはNuxt2のinject
関数が使用されています。
呼び出すにはNuxtインスタンスの$shopify
を使用します。
setup
内でNuxtインスタンスにアクセスするにはuseNuxtApp()
を使用します。
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
を付与する。
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
... 画像URLwidth
... 画像幅height
... 画像高さ
variants: []
... 価格情報の配列price
... 商品単価
在庫数や重量などは取得できませんでした。
商品一覧ページを確認しよう
商品一覧ページにアクセスしてみましょう。
アクティブな商品の情報が大量に表示されています。
注意!! コンテンツが取得できない場合
過去、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のコンテンツが取得できました。
今回の作業は以上です。
まとめ
今回はNuxt3からShopifyに登録した商品一覧をAPIで取得する設定を行いました。
これをうまく使用すると、商品管理、決済はShopifyに任せ、商品ページはNuxtで構築することができます。
いわゆるヘッドレスECサイトですね。
ここで紹介した技術は最初の最初の1歩ですが、ここからNuxt × ECサイトの可能性が広がりそうです。
また新しい情報を取得したらここで紹介しますね。お楽しみに。