Comment on page

Chrome Devtools

Testing performance and privacy rules with Chrome Devtools
If dealing with a complex page, a sluggish internet connection, or sluggish Bubble editor, it is best practice to create a copy of your target page before deleting or changing elements, just to have a sandbox where you can quickly delete things or make changes without breaking anything.

Get familiar with the network tab of Chrome

You can use the Network tab of Chrome's Developer Tools to see how your page is loading and what's taking up the most time/space. Here's a detailed guide to how to use the Network tab in general. For a more Bubble-specific intro, here's a quick guide to finding big searches and identifying which data is loaded onto the page:
  1. 1.
    Open the Developer Tools console in Chrome by going to View -> Developer -> JavaScript console.
  2. 2.
    Switch to the Network tab.
  3. 3.
    Load the page, you'll see something like the below screenshot.
  4. 4.
    Sort by Size, so that the biggest things are at the top (see screenshot 1 below).
  5. 5.
    If you see items called "search" or "msearch" at the top, those represent searches that the application is doing. Click on one to inspect it.
  6. 6.
    Expand the data shown in the Preview tab until you see what data is being shown (see screenshot 2 below).
Screenshot 1: List of largest operations on your page
Screenshot 2: What's getting downloaded with a single search operation
Here's what different types of requests might look like:
To only check for downloaded data (not plugin files, styles/fonts, images, or core page/bubble files), press the XHR filter:
MSearch requests will contain one or more search:
One search (returned one Website object)
2 different searches in same msearch response (email_template and property)
mget requests refer to request's that come from a lookup of a unique ID stored on another object. For example, if a User has a list of Stores (another object in your DB) stored directly on the User object, it is really storing a list of Stores' unique IDs. When you want to display some data about those Stores, or filter them or do some operation with them, an mget request is sent.
An example of this: Current User's Stores's Name would request all the Stores in this List of Stores.
Performance issues often arise when a search returns hundreds or thousands of items, or dozens of separate requests are taking place at the same time.
4 big searches happen at the same moment
A large search can be broken up into multiple responses. This happens if the search contains more than 400 results (as of April 2020).

What causes these searches and requests

Some of Bubble's best advice on these sorts of investigations came in this 2017 forum post from Josh.
Here is another useful forum thread on one-to-many data links (mget requests) vs searches.
Be aware that a search or msearch request isn't always directly triggered by a Bubble "Do a search for" data source. If the data isn't shown anywhere or used in the app logic, then it won't be loaded until it is needed. However, if you have a "Only when X" condition that relies on an element's data, this can cause data to need to be downloaded when that condition.
(show: element Conditionals must be evaluated.
referring to data sources of Repeating Groups, and performing operations like Filtering them from other groups, may require all of the RG's data to be downloaded
using an element's data source as a condition for a search will require that element's data source to be evaluated

Privacy Rules

To check whether your privacy rules are properly set up, you can look at the data returned in searches, MGet and msearch requests. The mget request, for example, returned a user's email (purple box):
If this isn't the "Current User" that is logged in, this is probably a privacy rules issue. Users won't be expecting other users to be able to see the email they used to sign up for your app.

Searches/patterns that can cause issues

When you identify a search request on your page that seems to be causing issues (downloading lots of data or holding up page loads), it's sometimes difficult to identify what is actually causing that search to be downloaded onto the page, since they aren't usually caused by simple searches. Maybe a condition on an element that causes the element to be visible - maybe a :sort when referring to a Repeating Group's content.
Some of the best information on this topic was provided by Josh from Bubble in 2017 in this forum thread.
Here is more information from Josh that is specifically about one-to-many data linking (e.g. User's Products) vs searches (Do a search for Products, with a constraint using a User).
  • :sorting, :filtering or :counting a repeating group's objects from another group
  • advanced filters (This Message's User's Name is "Test") can force data to be downloaded onto the page
  • using a repeating group's data as if it were a search
  • referring to another element's data source in conditional display logic
  • using an element's data source in a workflow's condition

Searching for Searches

Once you've identified a search, msearch or mget request that is inefficient, you may have trouble finding the source of that request if you're on a page with many searches.
If it is a search request, you're in a bit of luck. Using the following code from the DevTools network tab, you may be able to find the source of the search:
Finding the proper search_path
This may also be possible with msearch requests, but we've had less luck with them.
To use that search_path code, you need to paste it into the Console tab of the Chrome DevTools. The Chrome DevTools should be opened from your Bubble Editor for that app, not from the preview mode of the app (i.e. NOT from the same DevTools window where you found the search_path).
window.highlight('{"constructor_name":MORE_STUFF_HERE.....}');
Running the above search (click on this image to see fullscreen)
Often, this will not lead you to the element where the search actually takes place - maybe a Text element causes a search to be fired because of its data source, so this will take you to the Text which is using something likeRepeating Group's Users:filtered as a data source.
Sometimes multiple different groups will cause searches to be fired. This means that if you change one element that relies on a search, there may be several elements relying on the same data, so it will still be downloaded.
When using the Bubble capacity viewer, you can use the Chrome Devtools to examine the response that Bubble sends to your browser. It will contain the search_path values for all of the searches in the app that are using app capacity.