Filter blocks: Performance issues #45033
Replies: 0 comments 9 replies
-
I wonder if the Interactivity API could help in this case woocommerce/woocommerce-blocks#10582
Right, I've mentioned this also in my discussion topic https://github.com/woocommerce/woocommerce-blocks/discussions/10678 I guess some of the questions can be answered once we know how the filters are suppose to work in what context which is the discussion of the above linked discussion. |
Beta Was this translation helpful? Give feedback.
-
@senadir @mikejolley Are there any ways to prevent the fallback from rendering here? I tried returning just a string from the stock filter block (so no async request), but the fallback still renders. |
Beta Was this translation helpful? Give feedback.
-
Assuming we're using the filters with |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
In this post, I’m documenting and discussing the current performance issues of filter blocks to ensure we’re fixing the right issues.
Content flashing
From the moment the page starts rendering to the point when the filter blocks finish rendering, filter blocks are flashed a few times. This makes the site feel laggy and janky.
Screen.Recording.2023-08-21.at.16.10.23.mov
Let’s analyze the flashing timeline of the Stock Filter block to identify the causes of the issue. In the following sections, I use the term ‘flashing’, not ‘rendering’, to indicate the state when a visual change occurs. The block is rendered multiple times between those visual states.
The first flashing
At this point, the react and block scripts are loaded, and the block finishes rendering and showing the loading state.
<br><div data-block-name="woocommerce/stock-filter" data-heading="" data-lock="{"remove":true}" class="wp-block-woocommerce-stock-filter is-loading"></div><br><br>
<br><div data-block-name="woocommerce/stock-filter" data-heading="" data-lock="{"remove":true}" class="wp-block-woocommerce-stock-filter"><div class="wc-block-stock-filter style-list is-loading"><ul class="wc-block-checkbox-list wc-block-components-checkbox-list is-loading wc-block-stock-filter-list"><li style="width: 86%;"></li><li style="width: 40%;"></li><li style="width: 40%;"></li><li style="width: 85%;"></li><li style="width: 62%;"></li></ul></div><div class="wc-block-stock-filter__actions"></div></div><br><br>
The second flashing
Block content is replaced by
<Suspense>
fallback component.<br><div data-block-name="woocommerce/stock-filter" data-heading="" data-lock="{"remove":true}" class="wp-block-woocommerce-stock-filter"><div class="wc-block-stock-filter style-list is-loading"><ul class="wc-block-checkbox-list wc-block-components-checkbox-list is-loading wc-block-stock-filter-list"><li style="width: 86%;"></li><li style="width: 40%;"></li><li style="width: 40%;"></li><li style="width: 85%;"></li><li style="width: 62%;"></li></ul></div><div class="wc-block-stock-filter__actions"></div></div><br><br>
<br><div class="wc-block-placeholder"></div><br><br>
The third flashing
The block content replaces the fallback. We’re still in the loading state.
<br><div class="wc-block-placeholder"></div><br><br>
<br><div data-block-name="woocommerce/stock-filter" data-heading="" data-lock="{"remove":true}" class="wp-block-woocommerce-stock-filter"><div class="wc-block-stock-filter style-list is-loading"><ul class="wc-block-checkbox-list wc-block-components-checkbox-list is-loading wc-block-stock-filter-list"><li style="width: 86%;"></li><li style="width: 40%;"></li><li style="width: 40%;"></li><li style="width: 85%;"></li><li style="width: 62%;"></li></ul></div><div class="wc-block-stock-filter__actions"></div></div><br><br>
The fourth (the last) flashing
The loading state is replaced by the desired filter content. This is the point when the block finishes fetching collection data and building the options for display.
What should we do?
Ideally, the block content shouldn’t be flashing at all. We can do that if we server-side render the block (like what we do with the Mini Cart block), then render it client-side again when customers interact with it. But doing so means duplicating logic between PHP and JS, it’s not an issue with the Mini Cart due to the simplicity of the block markup, but filter blocks are way more complex than that. (I need your opinion on this, whether we should go with this direction or not).
If we want to keep rendering the block on the client side only, then we need to accept some trade-offs. Let’s examine those four flashings above further:
<Suspense>
from rendering the fallback.It takes time for filter options to show up
The block only starts fetching the collection data only after it finishes rendering. On slow networks or hosting, the duration is more noticeable.
We can solve this issue by hydrating the collection data request, like Cart and Check block does with the cart data. The challenge here is to detect the filter blocks on the page to produce the right request to hydrate.
cc @roykho @sunyatasattva What do you think? Is there anything I'm missing?
Beta Was this translation helpful? Give feedback.
All reactions