Liquid tarayıcıda değil, Shopify’ın sunucusunda render olur. Yavaş bir template, CDN’in arkasına saklayamayacağınız bir sunucu render süresidir. Döngüyü kötü yazarsanız, o maliyeti her istekte ödersiniz.
Neden cache kurtarmıyor
Shopify sayfaları büyük ölçüde her istekte yeniden render eder, özellikle sepet durumuna, müşteri oturumuna ya da query parametrelerine bağlı sayfalarda tam sayfa cache devreye girmez. {% for %} döngüsünün içinde her iterasyonda bir obje çözümlemesi (product.metafields, variant.price) oluyorsa bu maliyet sayfa her açıldığında tekrar ediyor.
Bunu fark etmenin yolu genelde şu: koleksiyon sayfası ürün sayısı arttıkça yavaşlıyor. Kod değişmedi, veri büyüdü.
İç içe döngü en pahalı desen
{% for collection in collections %}
{% for product in collection.products %}
{{ product.title }}
{% endfor %}
{% endfor %}
Dış döngü n koleksiyon, iç döngü her koleksiyon için ortalama m ürün dönüyorsa toplam iş n × m. Koleksiyon sayısı ya da ürün sayısı büyüdükçe bu çarpım katlanarak büyüyor, doğrusal değil.
Aynı sonuca genelde tek döngü ve önceden hazırlanmış bir liste ile ulaşılabiliyor. İç içe döngü gerekiyorsa iç döngüye mutlaka limit: koyun.
all_products döngü içinde arama yapmaz, listeler
{% for item in cart.items %}
{% assign p = all_products[item.product.handle] %}
{{ p.metafields.custom.something }}
{% endfor %}
all_products[handle] tek başına ucuz bir sözlük erişimi gibi görünüyor, ama sepet döngüsünün içinde her satırda tekrar çağrıldığında, satır sayısı arttıkça toplam maliyet artıyor. Sorun all_products’ın kendisi değil, onu bir döngünün içinde tekrar tekrar çağırmak.
Mümkünse bu veriyi döngü dışında bir kere çözün, döngü içinde sadece önceden hazırlanmış değişkeni kullanın.
{% render %} kapsamı izole eder, {% include %} etmez
{% render 'product-card', product: product %}
render çağırdığı snippet’e sadece verdiğiniz değişkenleri geçirir. Snippet üst şablonun tüm değişkenlerine erişemez, üst şablon da snippet’in içindeki değişkenleri görmez. Bu izolasyon hem hata ayıklamayı kolaylaştırıyor hem de değişken çözümleme maliyetini snippet’e verilenle sınırlıyor.
include kaldırıldı, kullanılmamalı. Üst kapsamın tamamını snippet’e açıyordu, bu da hem hangi değişkenin nereden geldiğini takip etmeyi zorlaştırıyor hem de gereksiz değişken çözümlemesine yol açıyordu. Hâlâ eski temalarda görülüyorsa render’a taşıyın.
Koleksiyonu tam iterasyon yerine paginate ile bölün
{% paginate collection.products by 24 %}
{% for product in collection.products %}
{% render 'product-card', product: product %}
{% endfor %}
{{ paginate | default_pagination }}
{% endpaginate %}
paginate olmadan collection.products döngüsü koleksiyondaki her ürünü tek seferde çekip render eder. Ürün sayısı 50’de sorun çıkarmaz, 5.000’de sayfa süresini gözle görülür şekilde uzatır. paginate render edilen ürün sayısını sabit tutuyor, koleksiyon büyüse de sayfa süresi büyümüyor.
limit: olmadan for tüm koleksiyonu döner
{% for product in collection.products limit: 4 %}
{{ product.title }}
{% endfor %}
“Son 4 ürün” ya da “önerilen 3 ürün” gibi bir bölüm için limit: yazmazsanız döngü koleksiyondaki tüm ürünleri dolaşır, sadece ilk dördünü kullanır, geri kalanı boşa render eder. limit: eklemek tek satır, maliyeti doğrudan sınırlıyor.
Hesaplanabilecek şeyi template’te hesaplamayın
Bir ürün için “kampanyalı mı” ya da “hangi kategoriye ait” gibi bir bilgi, her sayfa yüklemesinde Liquid içinde koşullarla hesaplanıyorsa, bu iş metafield’a taşınabilir. Değer bir kere admin’de ya da bir script ile yazılır, template sadece okur. Karşılaştırma ve döngü template’ten çıkar, okuma kalır.
Özet
Nested döngüden kaçının, gerekiyorsa limit: koyun. all_products erişimini döngü dışına alın. include yerine render kullanın. Büyük koleksiyonları paginate ile bölün, tek seferde tüm ürünü dönmeyin.