-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat. Collection - add pagination to limit the amount of fetched data #3688
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great change @ludoboludo! Let me add a little bit of context for anyone interested.
One of the most impactful Liquid performance tips is to make sure the code does as few iterations as possible. You don't want to waste any cycles going through the data that you don't actually need.
I used to think that having a limit:
in the for
loop should be enough to achieve this. You should still use it, but it's only a half of the equation.
I stumbled upon this issue when optimising one of the stores. It was suffering from high server response times on homepage. The layout was quite simple, all featured collection sections already were using the limit:
so I had to dig deeper into what's going on.
After consulting our Liquid folks, I learned that all collection.products
objects follow the default pagination rules. By default, they will fetch the first 50 products in the given collection. This is not an issue for small or simple catalogues, but can lead to longer queries when you have a lot of variants, prices, etc.
All in all, when iterating over a collection and using limit
, you should also use the paginate
as well. The former will limit the amount of iteration, the latter makes sure you're not over-fetching the data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sick!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my own understanding: do we need to use limit
on the forloop once we have a paginate in place?
From @krzksz's comment it sounds like paginate will fetch only products_to_show
items, that we then iterate on, so we don't risk running too many iterations already?
Or are we saying that the for loop will run through the whole collection but paginate won't output it all?
sections/featured-collection.liquid
Outdated
|
||
{%- if section.settings.collection.products.size > 0 -%} | ||
{% paginate section.settings.collection.products by section.settings.products_to_show %} | ||
{%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might be confused, but isn't using the paginate tag already giving us the "limit"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good point 🤔 In this context it doesn't seem like the limit
would be needed if the pagination alone is already limiting the amount of data fetched.
cc: @krzksz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a happy accident / unintended result of how these tags work and not best practice; either way just trying to understand these 2 tags better 😁
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated 👍 Removed the limit
from the for loop since like mentioned it's already being paginated.
I tried implementing this change in a theme I’m working on but noticed that the limit on products doesn’t seem to have any effect. After testing it on the Dawn theme, I observed the same issue there as well. I suspect pagination might not work with section.settings.collection at all. Based on the documentation here, it seems pagination might be limited to certain direct objects and may not apply to objects referenced through section settings. |
Hey @Matt-Kaminski!
Can you clarify what you mean by this? Is it the fact that you get more products then the @ludoboludo I think we need to release a hotfix for this change that restores the |
As you have noticed, the limit does not work correctly. I don't think there is a minimum number for the limit, but the pagination doesn't seem to work at all. At least, when I tested it, the limit had no effect regardless of the value set. I think it's possible that pagination only works when applied to global objects or arrays, not those retrieved from section settings. For example, it might work for: {% paginate collection.products by 10 %} but not for: {% paginate section.settings.collection.products by 10 %} I'm not entirely sure about this. Perhaps combining pagination with a limit, even for objects from the section settings, internally works in a way that optimizes performance. I suspect it might not because of limit not working. |
Got it! I'm sure that I think the main issue is that is still needs to be combined with the |
Just tested out that
On the other hand, it seems that any manipulation on the collection object also breaks things.
Seems like we probably should recommend using the |
Hmm weird, when I try the same code it's giving me a liquid error 🤔 Maybe we can pair on it to confirm where it's happening cc: @Roi-Arthur |
Ah correct… Only worked because I had another liquid block before that |
PR here to re add the limit on the forloop |
This is an extremely interesting optimization that I've never heard of. It seems a bit inutiitive though for it to be needed. Shopify can't optimize that with the limit? This should at least be documented somewhere as this feels to be an important perf optimization. |
@bakura10 we updated the docs with the info, though we need to update some more to re add |
PR Summary:
Wraps the forloop on the feat. collection section to limit the amount of fetched data, knowing we're only needing as many as our limit is suggesting.
Why are these changes introduced?
Fix concerns about performance.
What approach did you take?
Updated the forloop to be wrapped in a if statement.
Other considerations
Visual impact on existing themes
Shouldn't have any
Testing steps/scenarios
Demo links
Checklist