Skip to content

Core Data UI: move EntitiesSavedStates out of the editor into a dedicated package - #80022

Closed
enejb wants to merge 9 commits into
WordPress:trunkfrom
enejb:try/boot-core-data-ui
Closed

Core Data UI: move EntitiesSavedStates out of the editor into a dedicated package#80022
enejb wants to merge 9 commits into
WordPress:trunkfrom
enejb:try/boot-core-data-ui

Conversation

@enejb

@enejb enejb commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What?

Introduce @wordpress/core-data-ui, a small package that hosts the entity-save UI (EntitiesSavedStates), and move it out of @wordpress/editor. @wordpress/boot then renders it directly from core-data-ui, so @wordpress/editor — and its heavy @wordpress/block-library / @wordpress/media-utils dependencies — are no longer part of boot's dependency graph. The editor loads only when you're actually editing (the canvas loads it dynamically).

This is an alternative to #71948 (which moves EntitiesSavedStates into @wordpress/core-data). Putting React UI — which pulls in @wordpress/components, icons, clsx, etc. — into the data-only core-data package is a layering smell, so this variant keeps core-data pure data and introduces a dedicated UI package instead.

Why?

Follow-up to #79913 and its review. @wordpress/boot's always-mounted save UI statically imported EntitiesSavedStates from @wordpress/editor. Because a classic-script import lands in a script module's eager dependencies (static or dynamic), this forced @wordpress/editor and everything it pulls in — most significantly @wordpress/block-library (all core blocks) and @wordpress/media-utils — to load on every boot-powered view, including dashboard/list views that never open the editor.

#79913 deferred that with React.lazy, but as @youknowriad noted, that still couples boot to the editor. The right fix is to move the component to its correct layer so the editor isn't pulled in at all.

Scope of the load reduction

To be precise about what this removes: wp-core-data already declares wp-block-editor as a dependency on trunk (via its awareness/ code), so block-editor was already loading on boot-powered views regardless of this change. What this PR removes from those views is wp-editor, wp-block-library, and wp-media-utils — the bulk of the editor payload. Verified against the built assets: boot's module now depends on wp-core-data-ui and dynamically imports @wordpress/lazy-editor, with no wp-editor / wp-block-library / wp-media-utils in its static graph.

How?

  • New @wordpress/core-data-ui (classic script, handle wp-core-data-ui) exporting EntitiesSavedStates, EntitiesSavedStatesExtensible (private), and useEntitiesSavedStatesIsDirty. Depends on @wordpress/core-data + @wordpress/components, never on @wordpress/editor.
  • saveDirtyEntities implementation moves to a private @wordpress/core-data action (it's generic entity-save orchestration).
  • @wordpress/boot imports EntitiesSavedStates directly from core-data-ui, dropping the React.lazy/<Suspense> shim and the @wordpress/editor / @wordpress/lazy-editor re-export.
  • Carries over the @wordpress/build companion fix from Boot: lazy-load the editor instead of importing it eagerly in the save UI #79913 (routes enqueue their own classic deps, e.g. wp-viewport), which is still required once the editor stops loading on those views.

Backwards compatibility

This is intended to be fully non-breaking for consumers across all environments (npm, WordPress script handles, editors):

  • @wordpress/editor re-exports EntitiesSavedStates / useEntitiesSavedStatesIsDirty (public) and EntitiesSavedStatesExtensible (private) unchanged. getTemplateInfo / getTemplatePartIcon / the hasPostMetaChanges selector stay in editor.
  • The private core/editor saveDirtyEntities action is retained as a thin wrapper delegating to the new core-data action, so existing consumers keep working.
  • Behavior is preserved: the block-editor __unstableMarkLastChangeAsPersistent() undo marking stays (core-data already depends on block-editor), and the per-record "Post Meta." indicator is reproduced from core-data edits directly.
  • New package registration is automatic in the Gutenberg plugin. When synced to WordPress core, wp-core-data-ui needs adding to core's wp_default_packages_scripts() (standard new-package step). If ported to upstream WordPress/gutenberg, the package would also need a native build entry.

Deliberate scope choices

  • The pure getTemplateInfo / getTemplatePartIcon utils are duplicated into core-data-ui (they only depend on @wordpress/icons) rather than moved out of editor, to avoid re-pointing ~10 unrelated editor consumers. Open to consolidating later.

Testing Instructions

On the experimental Dashboard (Beta) page (gutenberg-dashboard-widgets experiment), which mounts @wordpress/boot:

  1. Enable "Dashboard (Beta)" and open it.
  2. DevTools → Network: confirm editor.min.js, block-library.min.js, and media-utils.min.js are not requested; core-data-ui loads; the page renders. window.wp.editor is undefined; window.wp.viewport is defined.
  3. In the Post/Site editor, make an entity change and Save (button and Cmd/Ctrl+S): the "Review changes" modal opens and saving works. The changes list renders exactly as before, including the per-record "Post Meta." note where applicable.
  4. Regression-check edit-site save button / save panel and the editor publish panels.

enejb and others added 6 commits July 6, 2026 12:02
…ated package

Boot's always-mounted save UI statically rendered `EntitiesSavedStates`
from `@wordpress/editor`. Because a classic-script import lands in a
module's eager dependencies, this forced the entire editor (block-editor,
block-library, media-utils) to load on every boot-powered view, including
dashboard/list views that never edit.

Rather than lazy-loading the editor (which still couples boot to it), this
moves the entity-save UI to its right layer: a new `@wordpress/core-data-ui`
package that depends on `@wordpress/core-data` + `@wordpress/components` but
never on `@wordpress/editor`.

- Add `@wordpress/core-data-ui` (classic script) hosting `EntitiesSavedStates`,
  `EntitiesSavedStatesExtensible`, and `useEntitiesSavedStatesIsDirty`.
- Move `saveDirtyEntities` to a private `@wordpress/core-data` action (it is
  generic entity-save orchestration). Drop the block-editor
  `__unstableMarkLastChangeAsPersistent()` coupling and the editor-state-coupled
  "Post Meta." per-record indicator (`hasPostMetaChanges`).
- `@wordpress/editor` re-exports the component/hook (public) and
  `EntitiesSavedStatesExtensible` (private) unchanged, so existing consumers
  (edit-site, editor) keep working; edit-site's save button now reads
  `saveDirtyEntities` from core-data.
- Boot imports `EntitiesSavedStates` directly from `@wordpress/core-data-ui`
  and drops the `React.lazy`/`Suspense` shim and the `@wordpress/editor` /
  `@wordpress/lazy-editor` re-export. The editor now loads only when the canvas
  mounts it (dynamic import), never from the shell.

Alternative to WordPress#71948 (which moved the component into `@wordpress/core-data`),
keeping the data package free of UI dependencies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added [Package] Core data /packages/core-data [Package] Editor /packages/editor [Package] Edit Site /packages/edit-site labels Jul 8, 2026
`@wordpress/core-data-ui` uses `lock`/`unlock` for its private
`EntitiesSavedStatesExtensible` export, so it must be in the core-modules
allowlist; otherwise loading the package (and therefore the editor, which
re-exports from it) throws at runtime.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the [Package] Private APIs /packages/private-apis label Jul 8, 2026
Address BC review of the EntitiesSavedStates relocation so consumers across
all environments are unaffected:

- Restore the private `core/editor` `saveDirtyEntities` action as a thin
  wrapper delegating to the new `core` (core-data) action, so external
  consumers of `unlock( dispatch( 'core/editor' ) ).saveDirtyEntities` and the
  documented private API keep working. edit-site's save button is reverted to
  the editor store (net zero change).
- Keep the block-editor `__unstableMarkLastChangeAsPersistent()` behavior in
  core-data's `saveDirtyEntities` (core-data already depends on block-editor
  via its awareness code, so this adds no new coupling), preserving undo
  behavior for every caller.
- Preserve the per-record "Post Meta." changes indicator in the moved
  component by computing it from core-data edits directly. The editor's
  `hasPostMetaChanges` selector only consulted editor state as a fallback for
  omitted args, which this call path never used, so the indicator is fully
  reproducible without the editor store.
- Document the new `saveDirtyEntities` private action under the core-data store
  in docs/private-apis.md.

Net effect: no public or private API removals, and no user-visible behavior
change, while boot still loads no editor code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot removed the [Package] Edit Site /packages/edit-site label Jul 8, 2026
Drop the verbose `//` comments added across this work; the code reads clearly
on its own. No functional changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Core data, [Package] Editor, [Package] Private APIs.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

2 similar comments
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Core data, [Package] Editor, [Package] Private APIs.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Core data, [Package] Editor, [Package] Private APIs.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: enejb <enej@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: Mamaduka <mamaduka@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@youknowriad
youknowriad requested review from aduth and talldan July 9, 2026 09:24
@youknowriad

Copy link
Copy Markdown
Contributor

I don't have a fixed opinion here but for me a new package is the least appealing option. I'd see:

  • Use "admin-ui" (accepting that admin-ui as a core-data dependency)
  • Use "core-data" (accepting that core-data offer some "Data" related components like saving and such)

Not strictly opposed to the new package but I'm not sure I like it to be honest, I fear the duplication of very close packages causing more confusion for contributors.

@youknowriad
youknowriad requested a review from Mamaduka July 9, 2026 09:27
@Mamaduka

Mamaduka commented Jul 9, 2026

Copy link
Copy Markdown
Member

Thanks for the ping!

Also, don't love the idea of a new package, which seems to have been introduced more recently.

Ideally, UIs like EntitiesSavedStates should be easily composable across any admin page, and I think the @wordpress/admin-ui package is meant to provide that.

What are the missing pieces to achieve this? What makes it hard to replicate this UI piece?

I know @WordPress/gutenberg-components forks are very busy, but they might have some options.

P.S. The core-data package also needs some dependency trimming (#67870).

@youknowriad

Copy link
Copy Markdown
Contributor

P.S. The core-data package also needs some dependency trimming (#67870).

The "why" is not clear to me here.

@Mamaduka

Mamaduka commented Jul 9, 2026

Copy link
Copy Markdown
Member

My understanding is that block-editor needs to be replaced with a slimmer handler for Footnotes. There's no need for the core-data package to pull in the block-editor and its dependencies for this single case.

@enejb

enejb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback @youknowriad and @Mamaduka!

I will add the components to the admin-ui to keep the separation of data and ui and use the existing admin-ui package. Will create a new PR to keep this moving.

@enejb

enejb commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

I am closing this in favour of #80074

@enejb enejb closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Core data /packages/core-data [Package] Editor /packages/editor [Package] Private APIs /packages/private-apis

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants