From 437f4b9ab9a9f5b5a0e9d73ed3174e6f063f823e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 29 May 2026 02:00:41 +0000 Subject: [PATCH] Perf: Defer widget-schema prefetch AJAX to requestIdleCallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 5 of the perf series. requestWidgetsConfig fetches ~394 KB of widget control schemas for widget types NOT used on the page (in-page widgets already have their schemas in the boot config). Currently fires synchronously during initEditor, so the response parse + 394 KB jQuery.extend(true,{},...) deep-merge into widgetsCache races with initial canvas render on the main thread. This defers the entire request body + send + response processing into requestIdleCallback (with a 3s timeout safety net, and setTimeout(0) fallback for browsers without rIC). The only thing waiting on it is the panel-loading spinner via panel/state-ready — the canvas is interactive immediately. Gated by the existing e_memoize_active_controls experiment. --- assets/dev/js/editor/editor-base.js | 33 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/assets/dev/js/editor/editor-base.js b/assets/dev/js/editor/editor-base.js index 567e9910da6d..9cb7cf403be1 100644 --- a/assets/dev/js/editor/editor-base.js +++ b/assets/dev/js/editor/editor-base.js @@ -1137,15 +1137,16 @@ export default class EditorBase extends Marionette.Application { } requestWidgetsConfig() { - const excludeWidgets = {}; + const run = () => { + const excludeWidgets = {}; - jQuery.each( this.widgetsCache, ( widgetName, widgetConfig ) => { - if ( widgetConfig.controls ) { - excludeWidgets[ widgetName ] = true; - } - } ); + jQuery.each( this.widgetsCache, ( widgetName, widgetConfig ) => { + if ( widgetConfig.controls ) { + excludeWidgets[ widgetName ] = true; + } + } ); - elementorCommon.ajax.addRequest( 'get_widgets_config', { + elementorCommon.ajax.addRequest( 'get_widgets_config', { data: { exclude: excludeWidgets, }, @@ -1166,7 +1167,23 @@ export default class EditorBase extends Marionette.Application { } ); } }, - } ); + } ); + }; + + // Defer the schema-prefetch (request body + ~394 KB JSON response parse + the + // per-widget deep-merge in addWidgetsCache) into idle time so it does not race + // with the initial canvas render. The data is only needed when the user opens + // the widget panel to add a new element; in-page widgets already have their + // schemas in the boot config. Falls back to setTimeout where requestIdleCallback + // is unavailable (Safari pre-15.4). + const useDefer = elementorCommon?.config?.experimentalFeatures?.e_memoize_active_controls; + if ( useDefer && 'function' === typeof window.requestIdleCallback ) { + window.requestIdleCallback( run, { timeout: 3000 } ); + } else if ( useDefer ) { + setTimeout( run, 0 ); + } else { + run(); + } } async refreshWidgets() {