Skip to content

Complete shared-extension-utils externalization to prevent duplicate store registration#47850

Draft
kraftbj wants to merge 18 commits intotrunkfrom
investigate-jetpack-1437
Draft

Complete shared-extension-utils externalization to prevent duplicate store registration#47850
kraftbj wants to merge 18 commits intotrunkfrom
investigate-jetpack-1437

Conversation

@kraftbj
Copy link
Copy Markdown
Contributor

@kraftbj kraftbj commented Mar 30, 2026

Fixes #34793

Proposed changes

  • Finish the externalization of @automattic/jetpack-shared-extension-utils by dropping the external: false opt-out for /store/wordpress-com and re-exporting wordpressPlansStore from the package root
  • Migrate Jetpack's runtime consumers to the root import so the shared package resolves once through the WP dependency
  • Remove the select() duplicate-registration guards (and their tests); the fix is now packaging behavior rather than local checks
  • Keep the shared UMD bundle in packages/assets, but enqueue its extracted CSS when the shared script handle is already enqueued
  • Switch the bundle's textdomain to jetpack-assets and add a babel override so bundled strings hit the existing assets-package translation infrastructure
  • Keep the minimal jetpackConfig shim for the shared UMD build
  • Update changelog entries to match the final scope; drop the connection changelog since that change reverted

Known follow-up: if Store "jetpack-connection" is already registered reappears on My Jetpack after backing out the connection-package guard, that's a separate architectural issue (jetpack-connection is in defaultRequestMap but not actually built as a UMD) and will be handled in its own PR.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

  1. Run composer test-php in projects/packages/assets.
  2. Run jp test js js-packages/shared-extension-utils.
  3. Run jp build packages/assets and confirm jetpack-shared-extension-utils.js and .css emit.
  4. Run jp build plugins/jetpack --deps.
  5. Confirm a Jetpack block editor .asset.php includes jetpack-shared-extension-utils as a dependency.
  6. Open the Jetpack block editor and confirm no duplicate-registration warnings for jetpack-modules or wordpress-com/plans.
  7. Confirm .has-warning.is-interactive block editor styles apply (validates the CSS enqueue hook).

The `jetpack-modules` and `wordpress-com/plans` stores were being
registered multiple times because shared-extension-utils was bundled
independently into every consumer's webpack output. This adds the
package to the webpack externals map and builds a single UMD bundle
via the assets package, following the same pattern used for
jetpack-script-data and jetpack-connection.

Also adds try/catch guards around store registration calls as
defense-in-depth against future regressions.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the investigate-jetpack-1437 branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack investigate-jetpack-1437
bin/jetpack-downloader test jetpack-mu-wpcom-plugin investigate-jetpack-1437

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: May 5, 2026
    • Code freeze: May 4, 2026

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@github-actions github-actions bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Mar 30, 2026
@kraftbj kraftbj removed the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label Mar 30, 2026
kraftbj added 5 commits March 30, 2026 15:47
The I18nCheckPlugin auto-detects textdomain from the host package's
composer.json (jetpack-assets), but the bundled shared-extension-utils
code uses its own textdomain. Override I18nCheckPlugin and
I18nLoaderPlugin to expect jetpack-shared-extension-utils.
Add phpcs:ignore for TextDomainMismatch and I18nTextDomainFixer since
the bundled code uses its own textdomain, not the host package's.
@github-actions github-actions bot added the [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ label Mar 30, 2026
@jp-launch-control
Copy link
Copy Markdown

jp-launch-control bot commented Mar 30, 2026

Code Coverage Summary

2 files are newly checked for coverage.

File Coverage
projects/packages/assets/src/class-shared-extension-utils-assets.php 6/15 (40.00%) ❤️‍🩹
projects/packages/assets/src/js/shared-extension-utils.js 0/0 (—%) 🤷

Full summary · PHP report · JS report

Coverage check overridden by I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage. .

@kraftbj kraftbj added the I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage. label Apr 16, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Externalizes @automattic/jetpack-shared-extension-utils to a shared WP script dependency to prevent duplicate bundling that can trigger duplicate Redux store registration errors in the block editor.

Changes:

  • Add @automattic/jetpack-shared-extension-utils to the webpack dependency-extraction request map and document the behavior.
  • Build a jetpack-shared-extension-utils UMD bundle in packages/assets and register it in PHP for use as a WordPress script dependency.
  • Add store registration guards and update related tests and test setup (including removing now-unneeded console error suppression).

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
projects/plugins/jetpack/tools/check-block-assets.php Updates the block view-script dependency allowlist.
projects/plugins/jetpack/changelog/externalize-shared-extension-utils Changelog entry for the Jetpack plugin allowlist update.
projects/packages/paypal-payments/tests/jest.setup.js Removes suppression of the “already registered” console error in tests.
projects/packages/paypal-payments/changelog/fix-duplicate-store-registration Changelog entry for PayPal Payments test setup change.
projects/packages/assets/webpack.config.js Adds a new build target to output the shared-extension-utils UMD bundle.
projects/packages/assets/src/js/shared-extension-utils.js Entry module re-exporting @automattic/jetpack-shared-extension-utils for bundling.
projects/packages/assets/src/class-shared-extension-utils-assets.php Registers the new jetpack-shared-extension-utils script handle in PHP.
projects/packages/assets/actions.php Hooks the new asset registration into WordPress load.
projects/packages/assets/package.json Adds the JS dependency and build tooling needed for the new bundle.
projects/packages/assets/changelog/externalize-shared-extension-utils Changelog entry for adding the new UMD bundle/registration.
projects/js-packages/webpack-config/src/webpack.js Externalizes the root shared-extension-utils package and exempts selected subpaths.
projects/js-packages/webpack-config/README.md Documents the new extracted dependency and the subpath exception behavior.
projects/js-packages/webpack-config/changelog/externalize-shared-extension-utils Changelog entry for webpack-config externals update.
projects/js-packages/shared-extension-utils/src/store/wordpress-com/index.ts Adds a guard to prevent duplicate store registration.
projects/js-packages/shared-extension-utils/src/store/wordpress-com/test/store-registration.test.js Adds tests for the wordpress-com store registration guard.
projects/js-packages/shared-extension-utils/src/modules-state/index.js Adds a guard to prevent duplicate modules store registration.
projects/js-packages/shared-extension-utils/src/modules-state/test/store-registration.test.js Adds tests for modules-state store registration guard and initial data population.
projects/js-packages/shared-extension-utils/src/hooks/use-module-status/test/index.test.js Extends mocks to accommodate updated modules-state registration logic.
projects/js-packages/shared-extension-utils/changelog/fix-duplicate-store-registration Changelog entry for the shared-extension-utils guard.
projects/js-packages/connection/state/store-holder.jsx Adds a guard to prevent duplicate connection store registration.
projects/js-packages/connection/changelog/investigate-jetpack-1437 Changelog entry for connection store registration guard.
pnpm-lock.yaml Lockfile updates for new/updated workspace dependencies.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread projects/js-packages/shared-extension-utils/src/modules-state/index.js Outdated
Comment thread projects/js-packages/webpack-config/README.md Outdated
Comment thread projects/js-packages/webpack-config/src/webpack.js Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 21 out of 22 changed files in this pull request and generated 5 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread projects/packages/assets/webpack.config.js
Comment thread projects/js-packages/connection/state/store-holder.jsx Outdated
Comment thread projects/js-packages/shared-extension-utils/src/modules-state/index.js Outdated
Comment thread projects/js-packages/shared-extension-utils/src/store/wordpress-com/index.ts Outdated
@kraftbj kraftbj marked this pull request as ready for review April 16, 2026 20:52
@kraftbj kraftbj requested a review from a team as a code owner April 16, 2026 20:52
@kraftbj kraftbj requested a review from jeherve April 16, 2026 20:52
@kraftbj kraftbj added [Status] Needs Review This PR is ready for review. and removed [Status] In Progress labels Apr 16, 2026
Comment thread projects/js-packages/connection/state/store-holder.jsx
Comment thread projects/js-packages/connection/state/store-holder.jsx Outdated
Copy link
Copy Markdown
Contributor

@anomiex anomiex left a comment

Choose a reason for hiding this comment

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

Subpath imports (/components, /icons, /site-type-utils, /store/wordpress-com) are explicitly excluded from externalization and continue to be bundled. Note: /store/wordpress-com has store registration side effects at module scope; the others are side-effect free.

I'm skeptical about this part. If we're going to externalize the package, we should probably fully do so instead of allowing subpath imports to bypass it. Especially we shouldn't allow a subpath import of the store that's the reason we're doing this in the first place.

It's possible this means that just the store bit should be its own package, which a non-externalized shared-extension-utils could re-export for back compat. Or (if it's possible) that we should externalize only that one subpath import (and make the stores available only via that subpath import, not via the barrel import).

Comment thread projects/js-packages/connection/state/store-holder.jsx
Comment thread projects/js-packages/shared-extension-utils/src/modules-state/index.js Outdated
Comment thread projects/js-packages/shared-extension-utils/src/store/wordpress-com/index.ts Outdated
Comment thread projects/packages/assets/src/class-shared-extension-utils-assets.php Outdated
Comment thread projects/packages/assets/src/class-shared-extension-utils-assets.php Outdated
Comment thread projects/packages/assets/webpack.config.js Outdated
…1437

# Conflicts:
#	projects/packages/assets/package.json
@kraftbj kraftbj marked this pull request as draft April 17, 2026 21:00
@kraftbj kraftbj added [Status] In Progress and removed [Status] Needs Review This PR is ready for review. labels Apr 17, 2026
@kraftbj kraftbj changed the title Externalize shared-extension-utils to fix duplicate store registration Complete shared-extension-utils externalization to prevent duplicate store registration Apr 17, 2026
@kraftbj
Copy link
Copy Markdown
Contributor Author

kraftbj commented Apr 17, 2026

Reworked in 30741fc based on the feedback in this review round.

The earlier version was doing two things at once — partial externalization plus duplicate-registration guards — and the guards were really compensating for the partial part. Backed out the guards and finished the externalization:

  • /store/wordpress-com is no longer specially bundled
  • shared-extension-utils re-exports wordpressPlansStore from the root
  • Jetpack runtime consumers import from the root, so the shared package resolves through the WP dependency once

On the assets side:

  • Dropped the css_path => null workaround; the shared bundle now enqueues its extracted CSS when the script handle is in use (with a PHP test covering the hook)
  • Switched the bundle's textdomain to jetpack-assets and added a babel override so bundled strings land in the existing assets-package translation infrastructure

Validation:

  • composer test-php in projects/packages/assets
  • jp test js js-packages/shared-extension-utils
  • jp build packages/assets
  • jp build plugins/jetpack --deps

Known follow-up: if Store "jetpack-connection" is already registered still shows up on My Jetpack after removing the connection-package guard, I'll handle that separately. jetpack-connection is in the defaultRequestMap but isn't actually built as a UMD, which is a separate architectural issue from this PR.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Jetpack JS: fix creation of multiple Redux stores

4 participants