A recent thread about the Bubble editor becoming sluggish over time spawned another discussion: reusable elements can speed up the editing of complex pages significantly, but as it was rightly pointed out, they can also make the editing of an app a lot more complicated. Having worked on some very large one-page apps, I’ve become a reusable group proponent by necessity. It’s a fact of life at the current stage Bubble is in, that as the number of elements and workflows increases, the editor becomes increasingly unresponsive, sometimes to the point of being almost impossible to work with, until you restart your browser.
Splitting the page into reusable groups and editing them one by one, on the other hand, doesn’t balloon the RAM usage in the same way, even if the total number of elements remains the same (or is even slightly higher, as the reusable itself is also an element). How noticeable is the difference? Night and day, in my experience.
As the thread spawned a discussion on the pros and cons of reusables, I thought I’d create this thread to share some of my own findings and mistakes I’ve made along the way (of which there are many).
What’s the purpose of a reusable element?
In short, a reusable element, as the name suggests, is used to store any number of elements that are used more than once on your site. Let’s say your users can log in to your app on several different places, it makes sense to create a reusable element to avoid creating the signup form several times and updating every one of them when something changes.
So far, most of you will agree. In this thread though, I’ll be discussing using reusables for groups that are not necessarily used more than once.
Why use reusables that way?
There are two reasons to do this:
- As mentioned in the thread opening, using reusables instead of creating all elements on the same page, drastically reduces the sluggishness of the editor
- For me personally, working with isolated parts of the site in its own window, undisturbed by hundreds of elements that are irrelevant to what I’m currently doing, makes sense. It’s easier to find the right elements and workflows, organize custom workflows, and keep a sensible folder workflow folder structure.
Ok great, let’s all do that!
But yeah, there are drawbacks of course. Working with reusables require meticulous planning, and well… experience working with reusables. Make a mistake, and you can easily set yourself up for a painful number of hours correcting it and regretting decisions made way back in the day when this all seemed like a good idea. So what’s to make of it?
When to use reusables
Before even thinking about using reusables in this way, consider the following points, and only use it…
- When you know that a page will become seriously complicated and from experience, you know it severely affects the performance of the editor
- If you find yourself struggling to find the right element and workflow, and want to work with them in an isolated environment
- You are confident enough in your own abilities with Bubble and reusables to know how to plan and execute it properly
When not to use reusables
- If the page you’re working on is not particularly complex
- If you’re inexperienced working with reusables
- If, after reading this thread, or based on your own experience, this will add more complications to your development than you’re comfortable with – I find it useful, but you may find it a pain in the ass.
So why do reusables complicate things?
Bubble is all about referencing stuff. You reference elements, database entries, states, and workflows all the time, in actions, conditions, and everything else. Placed inside a reusable element, however, you lose that link. Any element/workflow/state inside of a reusable element is contained within its own universe, oblivious to what’s going on outside, with a few exceptions.
In other words, whenever you need to set up a condition, workflow action, or anything else that references an element inside a reusable, you’ll get stuck looking for it.
Working with reusables to speed up the editor can oftentimes lead to nested resuable groups, which makes the communication even harder, as you’ll have to work through several layers of states or custom workflows to get a response.
So how can reusables communicate with the outside world?
Plugins aside, there are three ways a reusable can communicate with elements outside of itself:
- States: States placed on the reusable group itself (not elements inside it) are available from both sides. In other words, you can set a state on a reusable group from both inside and outside of it, and reference this state in any way. This can be used to share info, trigger workflows or whatever kinky stuff you’re into.
- Custom workflows: custom workflows inside a reusable can be triggered from the outside. It does not work the other way however. You use the command “Trigger a custom event from a reusable element” to do this.
- URL parameters: URL parameters can, of course, be read and manipulated from inside a reusable too, opening another channel of communication
Strategically placing custom workflows
Some custom workflows are used all across your app, and one thing you want to avoid when working with reusables is to having to update a bunch of workflows whenever you change something in one of them. In this way, reusables can come in very handy. Set up a reusable popup containing the workflows you need, and place that popup in any reusable where you need the workflow. Use Trigger a custom event from a reusable element to execute whenever needed. If you need to pass information to the workflow, use states in the popup.
Replacing workflows with API workflows
For repeated workflows, you can also choose to schedule an API workflow instead of keeping the workflow on the page. This allows you to execute it from anywhere in your app, reusable or not. Naturally, you should know the usage and limitations of API workflows before choosing this solution.
There are two plugins in particular that have made life with reusables easier, both made by gaurav.
The EnvVariables plugin let’s you place an element on a page that creates a global variable for you. What this means is that you can store any sort of information (text, number, date, data type, etc) in a named variable. How is this different from a state? In two ways:
- The variable is global, meaning that it can be referenced from anywhere, even reusables and nested reusables
- It can be autobound, meaning that it will auto-update whenever data is updated or a set of conditions change (unlike states)
- Whenever a EnvVariable is invisible, it doesn’t auto-update, meaning you will sometimes be confused by en empty value. Working with reusable elements in the way we’re talking about here usually means that they’re going to be going back and forth between visible and invisible states as your users use the app, meaning you may have to set up some custom workflows to update an EnvVariable element. How? By reassigning the value to the variable from where the data is supposed to be fetched, all visible EnvVariable elements will auto-update.
As the name suggests, an If-Then WF allows you to set up a workflow to run whenever one or more conditions are met. One element can contain up to six different conditions and accompanying workflows. How is it different from Do when condition is true?
- It can greatly reduce the number of workflows in your editor, because it allows you to pack six different conditions into one
- For workflows needed across reusables, you can easily copy the element between groups, instead of having to manually copy a bunch of workflows
- Somewhat unrelated to this discussion, the workflows can be triggered inside the cell of a Repeating Group, meaning you can reference elements in that cell from the workflow, even if the action is triggered by something outside of the RG.
Using the If-then WF plugin in combination with Env Variables can greatly increase efficiency when working with reusables.
Adding collapsible, invisible groups to speed up changes
We all know how painful it can be to move elements around once a page reaches a certain size. You want to add a simple input to a form, and suddenly you have to resize the page, move a shitload of groups downward to make room for the new input, move your floating groups that no longer align to bottom… I get a headache just thinking about it. Here’s what I do to avoid that:
- On every reusable, add a certain number of pixels to its height in addition to what’s needed for its content. I usually go with around 1500 pixels extra
- Add a group to the bottom of the reusable, with a height of 1500, invisible on page load and collapsed when hidden.
- This basically gives you 1500 extra pixels of wiggle room every time you change something. Instead of having to resize the reusable and every element underneath it on the page, you simply resize the collapsed group to make room.
- I sometimes place groups like this between certain elements on the page or in a reusable where I suspect I might want to make changes later. It adds minimally to the page load, and can save crazy amounts of time whenever changes are needed.
I’m currently finishing up a large project where reusable groups have been used all over the place to keep the editor lightweight and organize parts of the app in a way that makes sense to me and my collaborators. A sound question then, is would I choose to use reusables in that way again?
My personal response is, yes, I would. As long as it’s planned out in advance, and you know your way around the different methods, I don’t find reusables that hard to work with, to be honest. Still, like many other aspects of Bubble, in the end it’s up to your personal preferences and way of working. If this all sounds totally counter-intuitive, then by all means, ignore this thread and create awesome apps without it.
If this all seems interesting, on the other hand, I hope these tips can be of value.