Skip to content

Boot: lazy-load the editor instead of importing it eagerly in the save UI - #79913

Closed
enejb wants to merge 5 commits into
WordPress:trunkfrom
enejb:fix/boot-lazy-load-editor
Closed

Boot: lazy-load the editor instead of importing it eagerly in the save UI#79913
enejb wants to merge 5 commits into
WordPress:trunkfrom
enejb:fix/boot-lazy-load-editor

Conversation

@enejb

@enejb enejb commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

What?

Make @wordpress/boot load the editor lazily, so the block editor (and its heavy block-editor / block-library / media-utils dependencies) is only loaded on demand instead of eagerly on every boot-powered view. Includes a companion fix in @wordpress/build so routes reliably receive their own classic script dependencies.

Why?

@wordpress/editor is a classic script. Boot's SaveButton, SavePanel, and use-save-shortcut are part of the always-mounted shell and statically imported EntitiesSavedStates and the editor store from it. Because a classic-script import lands in a module's eager dependencies regardless of whether it is static or dynamic, this forced the entire editor (~2–3 MB of JS) to load on every boot-powered page, including list/dashboard views that never open the editor.

How?

1. @wordpress/boot + @wordpress/lazy-editor — defer the editor. The only way to defer a classic-script package is through a script-module boundary, which is what @wordpress/lazy-editor is:

  • @wordpress/lazy-editor: re-export EntitiesSavedStates.
  • boot save UI: render EntitiesSavedStates through a React.lazy wrapper that dynamically imports @wordpress/lazy-editor, behind <Suspense>. The "Review changes" modal only opens while editing — when the editor is already loaded by the canvas — so there is no added latency.
  • use-save-shortcut: reference the editor store by name (core/editor) via useRegistry instead of importing the store descriptor.

2. @wordpress/build — enqueue route classic dependencies (companion fix). Removing the eager editor surfaced a latent coupling: the generated boot page registered its prerequisites script with only @wordpress/boot's classic dependencies, so a route's own classic dependencies (e.g. @wordpress/viewport) were only present because the editor happened to pull them in. Generated pages now merge each route content/route module's declared classic dependencies into the prerequisites script, so every route reliably gets its classic dependencies independent of what boot loads.

Testing Instructions

Verified locally with wp-env on the experimental Dashboard (Beta) page (gutenberg-dashboard-widgets experiment), which mounts @wordpress/boot:

  1. Enable the "Dashboard (Beta)" experiment and open it.
  2. In DevTools → Network, confirm editor.min.js / block-editor.min.js are not requested on load (the editor stays lazy), while the page renders correctly.
  3. Confirm window.wp.editor is undefined on load but window.wp.viewport is defined (the route's own classic dep is present).
  4. In the Post/Site editor, make an entity change and Save (button and Cmd/Ctrl+S): the "Review changes" modal opens and saving works as before (a brief <Suspense> spinner may show on first open while @wordpress/lazy-editor resolves).

Before the companion fix, the Dashboard (Beta) crashed with "Cannot read properties of undefined (reading 'name')" because wp.viewport was no longer loaded; with it, the dashboard renders identically to trunk and the editor remains lazy.

@enejb
enejb requested a review from Copilot July 6, 2026 20:39
@enejb enejb added [Type] Performance Related to performance efforts [Package] wp-build /packages/wp-build [Package] Boot /packages/boot labels Jul 6, 2026
@enejb
enejb requested a review from youknowriad July 6, 2026 20:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces boot-powered page load cost by avoiding eager inclusion of the classic @wordpress/editor script from the always-mounted boot save UI, and ensures boot-generated pages reliably enqueue each route’s own classic-script dependencies (independent of whatever @wordpress/boot happens to load).

Changes:

  • Lazily render the editor-backed “Review changes” UI by dynamically importing @wordpress/lazy-editor behind React.lazy/<Suspense>, instead of statically importing from @wordpress/editor.
  • Update the boot save shortcut logic to reference the editor store by name (core/editor) via the data registry, removing the static @wordpress/editor store import from boot’s dependency graph.
  • Update @wordpress/build page templates to merge route content/route module classic dependencies into the prerequisites script dependencies, so routes reliably get their required classic globals.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/wp-build/templates/page.php.template Merges route module classic dependencies into the prerequisites script dependencies.
packages/wp-build/templates/page-wp-admin.php.template Same dependency merging for wp-admin integrated boot pages.
packages/wp-build/CHANGELOG.md Documents the route-dependency enqueueing bug fix in generated pages.
packages/lazy-editor/src/index.tsx Re-exports EntitiesSavedStates via a script-module boundary for lazy consumption.
packages/lazy-editor/CHANGELOG.md Documents the new EntitiesSavedStates export.
packages/boot/src/components/save-panel/use-save-shortcut.ts Removes eager editor store import; uses registry selectors/dispatch by store name.
packages/boot/src/components/save-panel/lazy-entities-saved-states.tsx Adds a lazily imported EntitiesSavedStates wrapper via @wordpress/lazy-editor.
packages/boot/src/components/save-panel/index.tsx Wraps “Review changes” UI in <Suspense> and uses the lazy wrapper.
packages/boot/src/components/save-button/index.tsx Same lazy “Review changes” rendering for the save button modal.
packages/boot/CHANGELOG.md Documents the editor lazy-loading enhancement for boot save UI.

@enejb

enejb commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

@youknowriad this is my attempt at lazy loading the editor and not having to load it on wp-build pages that don't need it.

I verified that it works on the new dashboard page.

I am not really sure how we should be tackling this? How can we verify that that this works on other wp build pages?

import { store as coreStore } from '@wordpress/core-data';
import { displayShortcut, rawShortcut } from '@wordpress/keycodes';
import { check } from '@wordpress/icons';
import { EntitiesSavedStates } from '@wordpress/editor';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this component doesn't belong in "editor" package. So instead of adding complexity, maybe the right solution is to move it to the right place. This is what I tried to do in this old PR #71948 (worth reviving?)

@youknowriad youknowriad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current PR lazy loads the editor but still loads it. the ideal IMO is that the editor is not loaded at all in boot. And we do that by moving the components to their right place.

cc @scruffian as I discussed something similar recently.

useSelect( coreStore );
const { hasNonPostEntityChanges, isPostSavingLocked } =
useSelect( editorStore );
const { savePost } = useDispatch( editorStore );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we replace these with things from "core-data" instead. Core Data should already have all what's needed to check dirtiness and things like that.

One thing that might be missing in "core-data" is the "save lock" behavior which probably belongs there, rather than "editor". I wonder if we should do a small refactor to move things there?

@enejb

enejb commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback @youknowriad

I am going to close this PR since this approach is not the one that we want.

I created another PR - #80022 which introduces another package core-data-ui (this made sense to me) and was also mentioned in the comments on #71948 but I don't have strong feeling about this.

I would be happy to rebase #71948 and try to merge that instead if that the preferred way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Boot /packages/boot [Package] wp-build /packages/wp-build [Type] Performance Related to performance efforts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants