Let me start by showing you something, on the following video, both apps are made on Bubble.
Now, can you tell what we changed to have such a performance difference?
If you had been me a few years ago, you’ll probably answer in a very condescending way:
This is just basic repeating group pagination 😒
Well, it is not, but actually, a little bit, let me explain — and I promise I’ll give you everything you need to implement it!
Here’s what we’ll cover:
In order words, we’ll upgrade our Bubble skills from this to that:
After seriously investigating repeating groups' behaviour last year at Flusk, and trying to implement image pre-fetching we discovered that the way Bubble processes images are not what we thought!
If you don’t know what pre-fetching is, that’s a way to reduce the perceived loading time of a repeating group using two tweaks:
Here’s how pre-fetching works on Bubble for visual learners:
Pre-fetching a repeating group can be achieved in many ways — the easiest is by using another repeating group, but we’ll get back to that later!
We then built our Bubble pre-fetcher, but… it didn’t work.
Usually, when your browser downloads the RG items when the user clicks on “see more” (blue bubble on the flowchart - in our case images), it knows that the items we pre-fetched are already in the cache, and can be used instead of downloading a new set of data.
But apparently, this was not the case with Bubble, and we found out why!
It all came from a specific way Bubble handles image elements.
This is the behaviour we expected to see happening:
Instead, this is what we observed:
Bubble sends a different version of the same image for each element because of its Imgix processing — a.k.a something to not send 1000px images when shown into a 10x10px element.
And this behaviour happens even without using the:processed with Imgx suffix on your image.
Try it yourself -or check this: add an image element and save the URL of the image in the editor, then preview and compare with the URL of the image on your rendered/previewed page!
See? It’s different! There’s now something in front of the URL that looks like dwdwa.cloudfront.net. That’s the Imgix processing.
Now, how does that affects our pre-fetching system?
Let me get us back to my flowchart:
When Bubble pre-fetches the images in the pre-fetcher repeating group, it downloads a unique version X of the images.
But when my user interacts with the “see more” button, my original repeating group looks for version Y of the images.
Since it can’t find it, it downloads the images again when the button is clicked, which kills the entire purpose of the pre-fetching!
To avoid this Imgix processing required for our pre-fetching system, we, therefore, need to use this simple trick by adding this parameter to our image URLs:
We talked enough, let’s jump right in.
In order to be able to prefetch a repeating group’s content, we need two elements as mentioned above:
Let’s start with a basic repeating group Main RG which will display a list of images from the database.
Somewhere, we’ll create a custom state that will hold the number of images to display, with a default value of 2 images.
We can now use this value to restrict the number of items to show in our Main RG
We almost have our pagination ready! The last step is to add a button for the user to be able to display more items.
This could also be done on scroll for an advanced UX design!
We’re done, you can check the result here in case you missed something.
So let’s first assess how fast our repeating group and images load:
The previous example was slow, right? I mean it’s Bubble, right?
Yes, but it’s Bubble for the newbies, and you’re about to become a pro of Bubble optimizing!
Now, we need a second repeating group, our Fetch RG, to display the same list and the same images.
Because this repeating group will actually be hidden somewhere (1px/1px) and load the number of images plus the number of images to prefetch!
So in our case, it will load 2+2 images, so when the user clicks on “see more”, the next 2 images will be ready!
Note: you can also prefetch more than 2 additional images if you expect the user to be scrolling fast
Once we’ve done that, we need to mind the issue we encountered earlier!
The Imgix processing is about to ruin our work because it will download different images from the Main RG and the Fetcher RG.
Remember the fix?
Simply add the following to your image element’s URL in both repeating groups:
Woohoo! We improved, and now our RG is loading faster whenever we click on the “see more” button.
Voilà, this is what it looks like, and here’s a record for you:
Yes, you may have noticed, but we’re now completely skipping the native Imgix processing!
But that’s not a victory, because Imgix is actually our friend.
It allows fast image compression and resizing on the server side, and this must be part of our optimization strategy!
The following part is a little more complex and irritating
So how do we keep pre-fetching knowing that:
Well, we don’t use image elements anymore 🥳
For the last example, we’re using HTML elements instead of image elements.
So let’s go ahead and replace our old image elements with freshly-designed HTML elements.
Inside, we still want to display an image, so we use the following code snippet:
<img src="[IMAGE]" width="100%" height="100%">
From there, we can then apply Imgix processing manually, by adding the Imgix server prefix, and the desired processing parameters at the end.
It looks like that:
<img src="https://d1muf25xaso8hp.cloudfront.net/https:[IMAGE_URL_ENCODED]?w=384&h=384&auto=compress&dpr=2&fit=max&q=50" width="100%" height="100%">
You just need to take care of formatting the URL as URL Encoded to ensure everything runs smoothly.
Here’s what it looks like for an image with dimensions provided, and quality to be set to 35%. The full list of Imgix parameters can be found here- and there are way more than in the native Bubble editor!
We then apply the same settings to our Fetcher RG to ensure they both download the same images while forcing the Imgix processing.
Hooray 🥳 We made it. The repeating group is now much faster.
See the result here or there:
Bubble isn’t slow, and we need to get this idea out of people’s minds, it’s just built to be accessible to everyone, and while this presents limitations, we can always overcome them! 🙌
The technique used above can be applied for different use cases, not only images!
If you’re interested in another in-depth tutorial about pre-fetching any data type, feel free to comment on my forum post and I’ll send it to you as soon as it’s released!
In the meantime, here are some sweet options:
Subscribe to Our Newsletter
In-depth Bubble tips
Best tools for Bubble
Reports and updates