27

I'm coming to Craft as someone experienced with Expression Engine templates. When I'm coding for EE I try to avoid certain big ticket performance hits, for example:

Using embeds excessively. Using the disable parameter. Using simple conditionals vs. advanced conditional when possible. Keeping a close eye on the query count. Etc.

In the Craft/Twig world, are there similar common pitfalls to avoid when thinking about template performance? What kind of things should I watch for?

2 Answers 2

29

Avoiding unnecessary DB queries is definitely the main thing to watch out for. Here’s an example that came up recently in support: Someone wanted to display the first 6 Matrix blocks in an entry, outputting them 2 at a time. Initially the template code looked something like this:

{% for block in entry.matrixField.limit(2) %}
    <!-- Get the 1st two items -->
{% endfor %}

{% for block in entry.matrixField.offset(2).limit(2) %}
    <!-- Get the next two items -->
{% endfor %}

{% for block in entry.matrixField.offset(4).limit(2) %}
    <!-- Get whatever's left, not more than 2 -->
{% endfor %}

Rather than doing that, we suggested that all 6 blocks be grabbed up front, and output 2 at a time using Twig’s slice filter:

{% set blocks = entry.matrixField.limit(6) %}

{% for block in blocks|slice(0, 2) %}
    <!-- Get the 1st two items -->
{% endfor %}

{% for block in blocks|slice(2, 2) %}
    <!-- Get the next two items -->
{% endfor %}

{% for block in blocks|slice(4, 2) %}
    <!-- Get whatever's left, not more than 2 -->
{% endfor %}

Remember that you can always see what DB queries are happening in a given request by enabling Dev Mode and checking your browser’s Javascript console, where all DB queries for the current request will be logged, ordered by how long they took. It will also show if the exact same query was run multiple times.

1
18

Template performance isn't a huge worry in Craft thanks to the built-in cache tag. Even if some code is taking time to process, it can be wrapped in that tag to greatly improve performance.

But to more thoroughly answer your question, the scenarios where that tag might have to be used generally revolve around the number of DB queries. Craft's relationship engine it's pretty great, but it can lead to templates making many DB calls. Sometime's they're unavoidable but you can squeeze a bit more performance out.

In particular, the ElementCriteriaModel (used to retrieve entries, assets, users etc) has some helpful, performance-enhancing methods. For example, instead of retrieving all entries for a section and then only selecting the first one, you can use the .first() method.

{# Fetches all entries #}
{% set firstEntry = craft.entries.section('yourSection').find()[0] %}

{# Only fetches first entry #}
{% set firstEntry = craft.entries.section('yourSection').first() %}
2
  • 1
    Just be careful that you understand the {% cache %} tag correctly. By default it generates a unique cache item for each URL that uses the block, and for large sites this can actually slow down your site over time. See craftcms.stackexchange.com/a/22642/5437
    – Simon East
    Oct 30, 2017 at 23:27
  • These days, first() is deprecated. Use one() instead. Jul 1, 2022 at 15:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.