Boot: lazy-load the editor instead of importing it eagerly in the save UI - #79913
Boot: lazy-load the editor instead of importing it eagerly in the save UI#79913enejb wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
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-editorbehindReact.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/editorstore import from boot’s dependency graph. - Update
@wordpress/buildpage 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. |
…spense into the shared lazy wrapper
|
@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'; |
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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 ); |
There was a problem hiding this comment.
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?
|
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 I would be happy to rebase #71948 and try to merge that instead if that the preferred way. |
What?
Make
@wordpress/bootload the editor lazily, so the block editor (and its heavyblock-editor/block-library/media-utilsdependencies) is only loaded on demand instead of eagerly on every boot-powered view. Includes a companion fix in@wordpress/buildso routes reliably receive their own classic script dependencies.Why?
@wordpress/editoris a classic script. Boot'sSaveButton,SavePanel, anduse-save-shortcutare part of the always-mounted shell and statically importedEntitiesSavedStatesand theeditorstore from it. Because a classic-script import lands in a module's eagerdependenciesregardless 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-editoris:@wordpress/lazy-editor: re-exportEntitiesSavedStates.EntitiesSavedStatesthrough aReact.lazywrapper 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) viauseRegistryinstead 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 classicdependenciesinto the prerequisites script, so every route reliably gets its classic dependencies independent of what boot loads.Testing Instructions
Verified locally with
wp-envon the experimental Dashboard (Beta) page (gutenberg-dashboard-widgetsexperiment), which mounts@wordpress/boot:editor.min.js/block-editor.min.jsare not requested on load (the editor stays lazy), while the page renders correctly.window.wp.editorisundefinedon load butwindow.wp.viewportis defined (the route's own classic dep is present).<Suspense>spinner may show on first open while@wordpress/lazy-editorresolves).Before the companion fix, the Dashboard (Beta) crashed with "Cannot read properties of undefined (reading 'name')" because
wp.viewportwas no longer loaded; with it, the dashboard renders identically to trunk and the editor remains lazy.