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点は徹底してください:
- ループ内でのデータ取得を避ける
- 画像は必ず最適化する
- 条件分岐は最小限に
DEMETIOでは、Liquidパフォーマンス監査サービスも提供しています。既存ストアの速度改善をご希望の方は、お気軽にご相談ください。
関連記事: