Shopify Liquid完全ガイド:パフォーマンスとベストプラクティス

Liquidとは?基礎理解

Shopify Liquidは、Shopifyストアのテーマ開発に使用されるテンプレート言語です。HTMLに動的コンテンツを埋め込み、商品情報やカート内容を表示するために不可欠なツールです。

しかし、不適切なLiquid実装はストアの速度を著しく低下させる可能性があります。本記事では、実際の開発現場で得た知見をもとに、パフォーマンスを重視したLiquidコーディングのベストプラクティスを紹介します。

パフォーマンスを殺すアンチパターン5選

1. ループ内でのオブジェクト取得

{% raw %}
<!-- ❌ BAD: ループ内でproduct objectを繰り返し取得 -->
{% for item in cart.items %}
  {% assign product = all_products[item.product.handle] %}
  {{ product.title }}
{% endfor %}

<!-- ✅ GOOD: 必要なデータはitemから直接取得 -->
{% for item in cart.items %}
  {{ item.product.title }}
{% endfor %}
{% endraw %}

影響: カート内に10商品あれば10回のデータベースクエリが発生。ページレンダリング時間が2-3秒増加する可能性があります。

2. 不必要なcollection全件取得

{% raw %}
<!-- ❌ BAD: コレクション全商品を取得してフィルタ -->
{% assign featured_products = collections.all.products | where: "tags", "featured" %}

<!-- ✅ GOOD: 専用コレクションを作成 -->
{% assign featured_products = collections.featured.products %}
{% endraw %}

3. 深すぎるネストループ

{% raw %}
<!-- ❌ BAD: 3重ループでO(n³)の計算量 -->
{% for collection in collections %}
  {% for product in collection.products %}
    {% for variant in product.variants %}
      <!-- 処理 -->
    {% endfor %}
  {% endfor %}
{% endfor %}

<!-- ✅ GOOD: ロジックを分割、ページネーション活用 -->
{% paginate collection.products by 20 %}
  {% for product in paginate.collection.products %}
    <!-- 処理 -->
  {% endfor %}
{% endpaginate %}
{% endraw %}

4. 画像サイズ指定なし

{% raw %}
<!-- ❌ BAD: オリジナルサイズを読み込み -->
<img src="{{ product.featured_image }}" alt="{{ product.title }}">

<!-- ✅ GOOD: 適切なサイズを指定 -->
<img
  src="{{ product.featured_image | image_url: width: 600 }}"
  srcset="{{ product.featured_image | image_url: width: 600 }} 1x,
          {{ product.featured_image | image_url: width: 1200 }} 2x"
  alt="{{ product.title }}"
  loading="lazy"
>
{% endraw %}

5. 条件分岐の過剰使用

{% raw %}
<!-- ❌ BAD: 同じ条件を繰り返しチェック -->
{% if product.available %}
  <button>カートに追加</button>
{% endif %}
{% if product.available %}
  <span>在庫あり</span>
{% endif %}

<!-- ✅ GOOD: assignで一度だけ評価 -->
{% assign is_available = product.available %}
{% if is_available %}
  <button>カートに追加</button>
  <span>在庫あり</span>
{% endif %}
{% endraw %}

パフォーマンス最適化テクニック

Lazy Loading の実装

{% raw %}
<!-- Above the fold(ファーストビュー)-->
<img src="{{ section.settings.hero_image | image_url: width: 1200 }}" alt="Hero">

<!-- Below the fold -->
<img
  src="{{ product.image | image_url: width: 400 }}"
  loading="lazy"
  alt="{{ product.title }}"
>
{% endraw %}

キャッシュフレンドリーなコード

{% raw %}
<!-- ✅ GOOD: staticなデータはキャッシュ可能 -->
<div data-product-id="{{ product.id }}">
  {{ product.title }}
</div>

<!-- ❌ BAD: cart依存でキャッシュできない -->
<div>
  カート内商品数: {{ cart.item_count }}
</div>
<!-- 代わりにJavaScriptで動的取得を推奨 -->
{% endraw %}

metafields活用で柔軟性を確保

{% raw %}
<!-- カスタムデータをmetafieldsに格納 -->
{% if product.metafields.custom.badge %}
  <span class="badge">{{ product.metafields.custom.badge }}</span>
{% endif %}
{% endraw %}

デバッグテクニック

Liquid変数の中身を確認

{% raw %}
<!-- 開発環境でのみ表示 -->
{% if shop.name contains 'Development' %}
  <pre>{{ product | json }}</pre>
{% endif %}
{% endraw %}

パフォーマンス計測

{% raw %}
{% assign start_time = 'now' | date: '%s' %}
<!-- 重い処理 -->
{% assign end_time = 'now' | date: '%s' %}
<!-- Console: {{ end_time | minus: start_time }}秒 -->
{% endraw %}

実装チェックリスト

開発完了前に必ず確認:

  • ループは3重以内に抑えているか?
  • 画像にwidth/height属性を指定しているか?
  • above the fold以外はloading=“lazy”を使用しているか?
  • 不要なall_productsアクセスはないか?
  • metafieldsでカスタマイズ可能な設計になっているか?
  • モバイルでの表示速度をLighthouseで確認したか?

まとめ

Liquidは強力ですが、不適切な使い方はストアの死を意味します。特に以下の3点は徹底してください:

  1. ループ内でのデータ取得を避ける
  2. 画像は必ず最適化する
  3. 条件分岐は最小限に

DEMETIOでは、Liquidパフォーマンス監査サービスも提供しています。既存ストアの速度改善をご希望の方は、お気軽にご相談ください。


関連記事: