Shopify&Gatsbyのヘッドレスコマース実装で躓いたこと

お久しぶりです!エンジニアの川島です。
日々の実装に追われているうちに、前回の記事投稿から10ヶ月近く経ってしまいました笑。
ただでさえShopifyは情報の変化が早いので、過去に投稿した記事もそろそろアップデートしたいですね……!
(連載途中のヘッドレスコマース解説記事も近いうちに再開したいと思っています)

さて、本記事では、既にヘッドレスコマース(Shopify + Gatsby)の実装を行なっている方向けに、私が実案件でハマった落とし穴ポイントをご共有したいと思います。
日本語情報がまだまだ少ない中、手がかりの一つに役立てていただければ幸いです。

※本記事における技術構成は下記のとおりです。

  • フロントエンド:GatsbyJS
  • バックエンド(ECシステム):Shopify
  • ビルド&デプロイ:Gatsby Cloud
  • ホスティング:Firebase

商品数が多い場合、gatsby-source-shopifyプラグインの応答が不安定になる

Gatsbyにはヘッドレスコマース構築に最適化されたスターターがいくつか存在します。
過去記事でも紹介しているとおり、私が利用しているスターターは「gatsby-shopify-starter」です。

とても便利ではあるのですが、このスターターで利用されているShopify情報取得用プラグイン「gatsby-source-shopify」は、ときどき動作が不安定になり、タイムアウトエラーを繰り返すことがあります。

主に商品数が多いストアで発生する事象であり、新規のストア開発時にはそれほど問題にならないのですが、原因を特定できずけっこうハマりました。

gatsby-config.jsで、gatsby-source-shopifyプラグインのpaginationSize値を明示すると解消されるケースもあるようです。

// Number of records to fetch on each request when building the cache
// at startup. If your application encounters timeout errors during
// startup, try decreasing this number.
  paginationSize: 250,

ただ、それでも上手く行かない場合もあるので、既存のShopifyストアをヘッドレスにリニューアルするような場合は、事前に検証するか、他のプラグインを検討しても良いかもしれません。

※プラグインのGitHub上では以下のissueが報告されています
[gatsby-source-shopify] timeout error on build | https://github.com/gatsbyjs/gatsby/issues/21110
[gatsby-source-shopify] Timeouts during load; Limit of 250 is too large? | https://github.com/gatsbyjs/gatsby/issues/14300

gatsby-source-shopifyのmetafields情報取得

同じくgatsby-source-shopifyプラグインの落とし穴です。
gatsby-source-shopifyプラグインは、デフォルトではShopifyのmetafields情報を取得できません。

NOTE: By default, all metafields are private. In order to pull metafields, you must first expose the metafield to the Storefront API.
https://www.gatsbyjs.com/plugins/gatsby-source-shopify/#how-to-use

metafields情報を取得するためには、ShopifyのStorefront APIに、GraphQL Admin APIを用いてmetafields情報を公開する必要があります。Shopify公式のチュートリアルに掲載されてはいるのですが、詳しい手順が解説されている訳ではないので、けっこう手間取りました……。

具体的な手順としては以下が必要になります。

  1. metafield情報を取得したいShopifyストアに、Shopify GraphiQL Appをインストールする
  2. Shopify GraphiQL App上でMetafieldStorefrontVisibilityレコードを作成する
    ※Query Variablesは適宜書き換えてください

上記手順により、metafields情報がホワイトリストに登録され、Storefront APIからアクセスが可能になります。
ただ、私が試した際は、アクセス可能になるまでタイムラグがあったため、上手くいかない場合は翌日以降にリトライすると通るかもしれません。
metafields情報が取得可能になっていれば、http://localhost:8000/__graphql 画面からも値を確認できるので、Gatsby内のGraphQL記述を適宜アップデートしてください。

以下のフォーラム投稿はVue.jsでの実装ですが、解決までの過程が参考になります。(プライベートアプリのAPIアクセス権限不足により失敗する場合があるようです)
Metafield Storefront Visibility Record | https://community.shopify.com/c/Storefront-API-SDKs/Metafield-Storefront-Visibility-Record/td-p/572701

Adobe Fontsのダイナミックサブセットが読み込めない →追記:解決

実案件で遭遇し、かなりハマりました……。
Webフォント読み込み用プラグイン「gatsby-plugin-web-font-loader」は、Adobe FontsのWebプロジェクトに日本語フォントが含まれていると、動作しません。

Adobe Fontsで日本語Webフォントを利用する際は、Adobe公式に記載されているとおり、ダイナミックサブセットの指定が必要なのですが、どうやらgatsby-plugin-web-font-loaderプラグインはダイナミックサブセットの読み込みに対応していないようです。
英字Webフォントの利用には問題なかったため、日本語Webフォントの利用をやめることで解決しました。
(何か良い方法をご存知の方がいらっしゃいましたら、コメントいただけると大変助かります……)

なお、gatsby-plugin-web-font-loaderはGatsby内で最もダウンロードされているWebフォント系プラグインであるにも関わらず、実は既にメンテナンスが止まっています
Gatsby公式のWebフォント利用ガイドでは、本プラグインを用いてAdobe Fontsを読み込んでいるため、ドキュメントどおりに作っていた場合ほどハマります。お気をつけください。

▼追記:解決しました
本件、Gatsby-plugin-web-font-loaderを使わず、head内にscriptタグを追加することで解決しました!
Gatsbyではscriptタグをそのままの形では記述できないため、「gatsby-plugin-react-helmet」を併用します。
React Helmetを用いて、src/components/layout.jsのようなサイト共通パーツを定義しているファイル内でAdobeのダイナミックサブセット読み込み用スクリプトを記述してください。

<Helmet>
  <script type="application/javascript">
    {`
      {
        (function(d) {
          var config = {
            kitId: 'ここにID',
            scriptTimeout: 3000,
            async: true
          },
          h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
        })(document);
      }
    `}
  </script>
</Helmet>

ネット上の投稿を見る限りでは、Helmetを用いて記述した場合、Gatsbyサイトの構成によってはローカルで動作していてもサーバーにデプロイすると動かない…というケースもあるようです。検証の際にはサーバー上で動作するかも併せて確認してください。
Helmetを用いずに、gatsby-ssr.jshtml.jsをカスタマイズする方法でも実現できそうです。
参考記事:How to add 3rd party script in your gatsby website

なお、AdobeフォントではなくGoogleフォントを利用するのであれば、Font Sourceというプラグインでフォントをセルフホスティングできるとのこと。
検証する機会があったら試してみたいと思います:)
参考記事:Gatsby.jsでのWebフォントの読み込み方 Gatsbyでフォントをセルフホスティングする方法

外部スクリプトやOGPまわりのチェック漏れ

最後に、gatsby-shopify-starterを使った場合の留意点として。
本スターターは、インストールの段階でGoogle Analytics用プラグイン「gatsby-plugin-google-analytics」が含まれており、トラッキングIDも記載されています。

{
  resolve: gatsby-plugin-google-analytics,
  options: {
    trackingId: "UA-134421805-1",
    anonymize: true,
    respectDNT: true,
  },
},

後から確認したとき、パッと見で既に設定済みのように見えるため、対応が漏れがちです。クライアント用のIDへの差し替えを忘れずに。

同じように、OGP記述用のseo.jsもインストール時から含まれているのですが、そのままでは情報がいくつか不足しているため(og:urlやog:imageなど)、リリース前にカスタマイズすることを忘れないようにしましょう。

おわりに

以上、ヘッドレスコマース実装で躓いたポイントのご共有でした。
GatsbyとShopifyによるヘッドレス実装の情報は(※英語であっても)まだまだ少なく、何かに引っかかっても類似事例を見つけられないケースが多々あります。
特にGatsbyプラグインに関しては、開発元のGitHub issueを確認しつつ、トライ&エラーで原因を探るのが一番近道なようです。
幸い、Shopifyの各API、Gatsbyプラグインともに日々アップデートが成されているため、今うまくいかないことも将来的には解決されるかもしれません:)
ヘッドレスコマース実装を試みている方の一助となれば幸いです。

記事カテゴリー