Hello Bubble forum
Posting some content for the community.
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:
- Understanding what pre-fetching is
- Limitations study
- Building a repeating group with pagination
- Building our pre-fetcher system
- Re-integrating Imgix with custom HTML
In order words, weāll upgrade our Bubble skills from this to that:
Understanding Prefetching
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!
Pre-fet-cin what?
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:
- Firstly: using pagination (you got meā¦) to only show a necessary amount of items in the repeating group in the first place, youāve probably seen those āsee moreā buttons, thatās it. This avoids loading hundreds of database items if the user is only willing to access the first row.
- Second: when the visible elements in the repeating group are loaded, we prepare/preload the next set of elements to be shown if the user clicks the āsee moreā button or scrolls down.
At this stage, there should be no loading time at all when the user interacts.
Hereās how pre-fetching works on Bubble for visual learners:
Considerable speed improvement happens when the user interacts.
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!
The Big Discovery
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:
Expected image load behaviour
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.
The actual image load behaviour
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!
The fix to The Solution
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:
?ignore_imgix=true
How to Build Pre-fetching in Bubble
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:
- A repeating group with pagination, which we will call āMain RGā
- The pre-fetching system can be done using CSS, JS, and many other ways but for the sake of simplicity, weāll just use another repeating group, which we will call āFetcher RGā.
1. Main RG with pagination
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:
2. Pre-fetching images with our Fetcher RG
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.
Huun, why?
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!
In the Fetcher RG, I add two more images to the list to fetch
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.
The same image (in yellow) is being downloaded twice because it has different URLs (version X and Y)
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:
3. But what about our friend Imgix
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:
- Bubble automatically adds Imgix processing to image elements
- We canāt use Imagix because it breaks the pre-fetcher
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:
Conclusion
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 the post and Iāll send it to you as soon as itās released!
In the meantime, here are some sweet options:
- Feel free to suggest any edits or suggestions (was this too complex, well explained?)
- Subscribe to our blog
- Check out what weāre doing at Flusk ā a hub for Bubble-based businesses and makers
- Or even just connect with me on LinkedIn, Iād love to have you around
Extras:
- Answer to @anon71899553 Implement progressive display when the user scrolls
- Using pre-fetching for single-page apps
Victor from Flusk
Flusk - a hub of tools and services for Bubble makers and businesses