Skip to content

pat-contentbrowser: keep add-on components registered under the default key - #1637

Merged
petschki merged 1 commit into
5.6.xfrom
fix-contentbrowser-default-component
Sep 11, 2026
Merged

pat-contentbrowser: keep add-on components registered under the default key#1637
petschki merged 1 commit into
5.6.xfrom
fix-contentbrowser-default-component

Conversation

@petschki

Copy link
Copy Markdown
Member

The pattern registered its default SelectedItem component in init(), on every widget initialization, and @plone/registry overwrites silently. An add-on that registered its own component under the default key "pat-contentbrowser.SelectedItem" was therefore reset by the next content browser that initialized, so replacing the component site-wide only worked via a custom key plus the componentRegistryKeys pattern option.

The default component is now only registered if nothing is registered under that key yet. An add-on registration wins no matter whether the add-on bundle initializes before or after the pattern.

…default key

The pattern registered its default SelectedItem component in init(),
on every widget initialization, and @plone/registry overwrites
silently. An add-on that registered its own component under the
default key "pat-contentbrowser.SelectedItem" was therefore reset by
the next content browser that initialized, so replacing the component
site-wide only worked via a custom key plus the componentRegistryKeys
pattern option.

The default component is now only registered if nothing is registered
under that key yet. An add-on registration wins no matter whether the
add-on bundle initializes before or after the pattern.
@petschki
petschki requested a review from thet September 10, 2026 11:22
@petschki

petschki commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

Timing considerations: add-on component registration vs. pattern initialization

This is about whether an add-on registering a component in @plone/registry (under the default key with this PR, or under a custom key via componentRegistryKeys as before) reliably wins against the pattern's own initialization when the add-on ships as a module federation remote.

Short version: there is a theoretical timing window, but this PR neither widens nor narrows it. It is exactly the same window the custom-key mechanism already has today. The guard only changes which key the add-on wins under, not when the content browser looks the component up.

Why the window exists — the sequence after DOMContentLoaded

Add-on chain: the MF helper (@patternslib/dev/webpack/module_federation.js) calls initialize_remote() for every registered bundle → container.get("./main") fetches the remote's main chunk (fetch 1) → its import("./overrides") fetches the actual override chunk (fetch 2, required for the shared-dependency negotiation) → only then registerComponent() runs.

Pattern chain: registry.scan()new Pattern(el)setTimeout(0)init()register_default_components() (fetches SelectedItem.svelte only if the key is still empty) → fetch App.sveltemountSelectedItems.svelte calls getComponent(...) once in onMount and caches the result in RegisteredSelectedItem.

Both chains need roughly two sequential chunk fetches; which one finishes first depends on chunk sizes and HTTP behavior. In my live tests the add-on won both times (the App.svelte chunk is large, which buys time), but nothing guarantees it.

The crucial point: if a widget gets there first, it caches the default component for its whole lifetime. An add-on registration arriving later only takes effect for the next widget that initializes (e.g. in a modal opened later). The custom-key path behaves identically: key not registered yet → fallback to the default → cached.

What would make it deterministic (upstream work, independent of this PR)

  1. Small step, content browser: don't cache the component in onMount; resolve it from the registry in LoadSelectedItemComponent on every item render. Late registrations would then apply to everything the user selects afterwards. Preselected relations rendered at load time would still race, though.
  2. Systemic step, Patternslib: let the MF helper await all initialize_remote() promises and dispatch the event only afterwards, and let registry.init() defer the initial scan while MF bundles are registered but not yet initialized — with a timeout so a broken remote cannot block the page. This would make every add-on registration deterministic, patterns included, not only components. I think this could be the actual fix for our problem.

/cc @thet @MrTango

@thet thet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM! simple and fine fix for this problem.

@petschki

Copy link
Copy Markdown
Member Author

/run-coredev-6.2-robottests

@petschki
petschki merged commit b1ca998 into 5.6.x Sep 11, 2026
3 checks passed
@petschki
petschki deleted the fix-contentbrowser-default-component branch September 11, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants