WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.52k stars 4.21k forks source link

showInsertionPoint lag on chromium based browsers #65718

Open JacobSussan opened 1 month ago

JacobSussan commented 1 month ago

Description

showInsertionPoint (the function that handles inserting the blue lines that show where a block will be placed) is laggy on chromium based browsers.

I believe the styles for every block on the page are being recalculated multiple times per second when dragging a new block around.

Video: https://imgur.com/a/xUtyFyf

The more plugins that add custom blocks you have installed, and the more blocks you have on the page, the more lag you get.

If we update the function to return null (this will skip showing the blue lines):

function showInsertionPoint(rootClientId, index, __unstableOptions = {}) {
  return null;
}

We get this: https://imgur.com/a/6kmWJgY (no lag)

Step-by-step reproduction instructions

  1. Fresh install wordpress. Tested on 6.6.2 and 6.7
  2. Install some plugins that add custom blocks. (optional) 2.1. Stackable, Getwid, WooCommerce
  3. Add a bunch of blocks to a page
  4. Try to drag a new block around the block editor, as shown in the video

Screenshots, screen recording, code snippet

https://imgur.com/a/xUtyFyf

Environment info

Please confirm that you have searched existing issues in the repo.

Please confirm that you have tested with all plugins deactivated except Gutenberg.

JacobSussan commented 1 month ago

A simple solution might be debouncing the function:

function debounce(func, wait) {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

const debouncedShowInsertionPoint = debounce((dispatch, rootClientId, index, unstableOptions = {}) => {
  const { unstableWithInserter, operation, nearestSide } = unstableOptions;
  dispatch({
    type: 'SHOW_INSERTION_POINT',
    rootClientId,
    index,
    unstableWithInserter,
    operation,
    nearestSide
  });
}, 100);

function showInsertionPoint(rootClientId, index, unstableOptions = {}) {
  return ({ dispatch }) => {
    debouncedShowInsertionPoint(dispatch, rootClientId, index, unstableOptions);
  };
}

here is a 100ms debounce: https://imgur.com/a/wAVI1bV

JacobSussan commented 1 month ago

since I was asked... while waiting for this, you can debounce via your themes functions.php file by overwriting the following functions.

hacky code ahead:


function gutenberg_insertion_point_debounce_inline_script() {
    ?>
    <script>
    (function(wp) {
        var oldShowInsertionPoint = wp.data.dispatch('core/block-editor').showInsertionPoint;

        function debounce(func, wait) {
            var timeout;
            return function executedFunction(...args) {
                var later = function() {
                    clearTimeout(timeout);
                    func(...args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        }

        var debouncedShowInsertionPoint = debounce(function(rootClientId, index, unstableOptions) {
            oldShowInsertionPoint(rootClientId, index, unstableOptions);
        }, 200);

        wp.data.dispatch('core/block-editor').showInsertionPoint = function(rootClientId, index, unstableOptions) {
            debouncedShowInsertionPoint(rootClientId, index, unstableOptions);
        };
    })(window.wp);
    </script>
    <?php
}
add_action('admin_footer', 'gutenberg_insertion_point_debounce_inline_script');