One of my apps is still on Blaze, and I am trying to implement an endless scroll feature there. So, I initially get about 50 elements, then, once the user scrolls down, another 30 elements are being fetched and so on. This is done using a reactive variable.
I noticed that Blaze shows a quite inconsistent rendering behaviour. Most of the times, after setting the reactive var to a new set of elements, rendering is pretty fast (about 150ms). But sometimes, it takes ages (1-2s) until Blaze’s renderer actually reacts on the changed reactive var, by running the helper that actually retrieves the new value. This leads to a quite wonky user experience.
I am wondering what is causing these huge delays, and if there’s any way of speeding this up?
Another thing I noticed is that the helper gets twice on every update. I don’t see any reason for this, as the reactive var is only changed once, and the helper does not depend on any other reactive source. Any ideas what may cause this?
How are your subscriptions setup? Are you subscribing multiple times (one subscription per page of data) or a single subscription that sends all data that changes for every page?
Are you storing the data inside a reactive variable? That is your problem.
Blaze, or any front-end framework for that matter, cannot distinguish which objects inside the variable are updated, and so it must update the entire view from scratch.
Instead, try storing your data inside a local minimongo collection, and updating your data through there. It can be more efficient because documents are tracked by their _id.
You can initiate a local minimongo collection like this:
var cache = new Mongo.Collection(); // client only
For a further boost, you can filter in the fields that you want to display when returning the cursor to Blaze. That way, it doesn’t have to set up unnecessary Tracker instances.
Thanks for the hint, good point. I did not use a local collection in this case, because the order of the elements in the endless scrolling list matters, but the elements themselves are retrieved randomly. I might add a kind of “order” attribute to them, though, maybe then the performance gets better. Still, the problem I am seeing is not the rendering time, it is the time until rendering actually occurs. I now saw that I can speed up rendering if I do a Tracker.flush() right after the elements have been retrieved. This somewhat eliminated the long delays, but the double-run of the helper is still happening.
Here’s another way to look at it. Whenever you update the reactive-var, you are essentially removing the old data and putting in new data. With minimongo, you can use the upsert function to only update the data where necessary. This means you would have less re-runs.
And thus, this is not a Blaze issue, but a data layer and reactivity issue, which is not really an issue
On the helper getting called multiple times: are you updating the reactive-var in an autorun block? If so, what else are you updating in the same block? Having a lot of things going on in an autorun block leads to all kinds of things getting called numerous times. I’ve found success in breaking out bulky autorun blocks into separate distinct autorun blocks that each only manage one thing.
Using a local collection helped, indeed. Rendering times are much faster, and the helper is only called once (for the lifetime of the template, interestingly). Thanks!