Skip to content

Add wpPlugin.packageSources via pnpm patch on @wordpress/build#48089

Open
retrofox wants to merge 4 commits intotrunkfrom
update/wp-build-package-sources
Open

Add wpPlugin.packageSources via pnpm patch on @wordpress/build#48089
retrofox wants to merge 4 commits intotrunkfrom
update/wp-build-package-sources

Conversation

@retrofox
Copy link
Copy Markdown
Contributor

@retrofox retrofox commented Apr 14, 2026

What?

Patches @wordpress/build@0.11.0 to add wpPlugin.packageSources. This config lets wp-build discover, externalize, and bundle shared packages that live outside ./packages/, preserving their npm identity as script module IDs.

Closes WOOA7S-1341 WOOA7S-1342

Why?

@wordpress/build only scans ./packages/ for compilable packages. Shared packages in Jetpack's js-packages/ (like @automattic/number-formatters) get inlined into each consumer's bundle, duplicating code and breaking script module deduplication.

This is the bridge approach: a pnpm patch that mirrors the upstream PR 1:1 until Core merges it. Zero Jetpack-specific logic.

How?

pnpm patch (.pnpm-patches/@wordpress__build@0.11.0.patch)

Three changes to @wordpress/build:

  1. Per-package externals: Named sources listed in packageSources are externalized individually via exact-match onResolve handlers, instead of inferring the entire @scope/* as external.

  2. Skip transpilation for external sources: Packages from packageSources are pre-built by their own build system. wp-build only bundles them as script modules, skipping transpilePackage().

  3. wpScriptModuleExports on shared packages: Shared packages declare wpScriptModuleExports in their package.json so the externals plugin can detect them as script modules and track dependencies in .asset.php.

Validation with premium-analytics

The dashboard route imports @automattic/number-formatters to demonstrate both import modes:

  • Static import (formatNumber): compiled as a script module dependency with 'import' => 'static' in the asset metadata
  • Dynamic import (formatNumberCompact): loaded via React.lazy + Suspense, tracked as 'import' => 'dynamic' in the asset metadata

Both modes produce a single shared script module registered under @automattic/number-formatters, with no build artifacts inside js-packages/number-formatters/.

Patch lifecycle

When Gutenberg merges #77226 and Jetpack upgrades @wordpress/build: delete the patch, remove the entry from pnpm-workspace.yaml, run pnpm install.

Trade-offs

packageSources extends the same shared-module trust model that externalNamespaces already applies to @wordpress/* packages. All consumers of the same packageSources entry share a single script module registration in WordPress's global registry — last plugin to load wins if versions differ.

Within the monorepo this is mitigated by the shared lockfile; cross-release version skew is the real risk (plugin A on release N, plugin B on release N-1).

PR #48095 adds PHPUnit tests that document and verify this behavior.

Testing

  • Install
pnpm install
  • Build
pnpm --filter @automattic/jetpack-premium-analytics run build
  • Build output shows Bundled @automattic/number-formatters in Phase 2
image
  • build/modules/registry.php lists @automattic/number-formatters with its npm identity preserved
<?php
/**
 * Script module registry - Auto-generated by build process.
 * Do not edit this file manually.
 *
 * @package jpa
 */

return array(
	array(
		'id' => '@automattic/number-formatters',
		'path' => '@automattic/number-formatters/index',
		'asset' => '@automattic/number-formatters/index.min.asset.php',
	),
	array(
		'id' => '@jetpack-premium-analytics/init',
		'path' => 'init/index',
		'asset' => 'init/index.min.asset.php',
	),
);
  • build/routes/dashboard/content.min.asset.php tracks number-formatters as static + dynamic dependency:
<?php return array(
	'dependencies' => array( 'react-jsx-runtime', 'wp-element', 'wp-i18n' ),
	'module_dependencies' => array(
		array( 'id' => '@automattic/number-formatters', 'import' => 'static' ),
	),
	'version' => '...',
);
  • No build/ or build-module/ artifacts inside js-packages/number-formatters/
  • pnpm --filter @automattic/jetpack-forms run build still succeeds (regression check)

The Analytics page: <hostname>/wp-admin/admin.php?page=jetpack-premium-analytics

image

@retrofox retrofox requested a review from a team as a code owner April 14, 2026 14:15
@retrofox retrofox self-assigned this Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 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 update/wp-build-package-sources branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/wp-build-package-sources
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/wp-build-package-sources

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 Apr 14, 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 🤖


🔴 Action required: Please include detailed testing steps, explaining how to test your change, like so:

## Testing instructions:

* Go to '..'
*

🔴 Action required: We would recommend that you add a section to the PR description to specify whether this PR includes any changes to data or privacy, like so:

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

My PR adds *x* and *y*.

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!


Premium Analytics plugin:

No scheduled milestone found for this plugin.

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 Apr 14, 2026
@jp-launch-control
Copy link
Copy Markdown

jp-launch-control bot commented Apr 14, 2026

Code Coverage Summary

This PR did not change code coverage!

That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷

Full summary · PHP report · JS report

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.

Move to the existing .pnpm-patches/ directory.

Also, I'm not terribly fond of the "apply a large patch I hope to get merged upstream soon" approach here; such hopes seem frequently dashed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's fair. We need to try to move these changes upstream asap.

Comment thread patches/README.md Outdated
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.

Unneeded. Any comments about a patch can be included at the top of the patch file itself, as shown by the existing patches.

Comment thread projects/packages/analytics/.phan/baseline.php Outdated
@retrofox retrofox marked this pull request as draft April 14, 2026 15:22
@retrofox
Copy link
Copy Markdown
Contributor Author

@anomiex PR is not ready for review. Sorry about it. We need to land the package and plugin PRs first

@anomiex
Copy link
Copy Markdown
Contributor

anomiex commented Apr 14, 2026

Will this idea cause problems if multiple different wp-build-using plugins each include incompatible versions of @automattic/number-formatters?

It looks like, unless all plugins are careful to only load their build/build.php when needed and no two ever do it on the same request, the last plugin will "win" even if it has an older version of @automattic/number-formatters.

@retrofox retrofox force-pushed the update/premium-analytics-plugin branch from 6f55a70 to ae38a48 Compare April 14, 2026 17:58
@retrofox retrofox force-pushed the update/wp-build-package-sources branch from a53fd17 to 7ccaa1a Compare April 14, 2026 18:14
@retrofox
Copy link
Copy Markdown
Contributor Author

Will this idea cause problems if multiple different wp-build-using plugins each include incompatible versions of @automattic/number-formatters?

It looks like, unless all plugins are careful to only load their build/build.php when needed and no two ever do it on the same request, the last plugin will "win" even if it has an older version of @automattic/number-formatters.

Great point. As far as I understand, this is inherent to WordPress's global script module registry, not specific to packageSources.

The same trade-off already exists with externalNamespaces: when a plugin declares externalNamespaces: { wordpress: { ... } }, it trusts that the @wordpress/* modules in the environment are compatible. packageSources extends that same trust model to specific named packages.

Looking at the generated modules.php, wp-build calls wp_deregister_script_module() before wp_register_script_module(), so the last plugin to load wins.

Within the Jetpack monorepo, this is mitigated by the shared lockfile: all plugins built from the same commit get the same version of @automattic/number-formatters. The real risk is cross-release version skew, which is the same problem wp_register_script() has always had with shared dependencies.

Without packageSources, each consumer bundles its own copy inline. No collision, but no deduplication either. packageSources trades isolation for deduplication, the same trade-off externalNamespaces already makes.

This is a crucial point to keep in mind as more plugins adopt this pattern.

Does it make sense?

@anomiex
Copy link
Copy Markdown
Contributor

anomiex commented Apr 14, 2026

Something to keep in mind is that it doesn't seem like the people working on wp-build are considering these sorts of edge cases; they seem pretty focused on Gutenberg and Core. You should probably copy that information to your WordPress/gutenberg#77226 PR.

@simison
Copy link
Copy Markdown
Member

simison commented Apr 15, 2026

Note to also keep testing Forms builds and works well with this, as it's the only other thing using WP Build: jetpack build packages/forms

@retrofox retrofox force-pushed the update/premium-analytics-plugin branch from 2eafa61 to ecf8b90 Compare April 15, 2026 13:49
@retrofox retrofox force-pushed the update/wp-build-package-sources branch from 7ccaa1a to e9b7a96 Compare April 15, 2026 16:54
@retrofox retrofox marked this pull request as ready for review April 15, 2026 16:57
@retrofox
Copy link
Copy Markdown
Contributor Author

Addressed all three:

@retrofox
Copy link
Copy Markdown
Contributor Author

Something to keep in mind is that it doesn't seem like the people working on wp-build are considering these sorts of edge cases; they seem pretty focused on Gutenberg and Core. You should probably copy that information to your WordPress/gutenberg#77226 PR.

Good idea. I'll add the script module collision analysis to the Gutenberg PR #77226 so upstream maintainers are aware of the deduplication trade-off.

@retrofox
Copy link
Copy Markdown
Contributor Author

Note to also keep testing Forms builds and works well with this, as it's the only other thing using WP Build: jetpack build packages/forms

Confirmed. pnpm --filter @automattic/jetpack-forms run build passes with the patch applied. All build steps complete successfully (blocks, contact-form, dashboard, wp-build, form-editor, modules).

Base automatically changed from update/premium-analytics-plugin to trunk April 16, 2026 07:07
@retrofox retrofox force-pushed the update/wp-build-package-sources branch 2 times, most recently from dd7ccc7 to 8610eb4 Compare April 16, 2026 09:07
patches @wordpress/build@0.11.0 to add packageSources config for
cross-directory package discovery. mirrors upstream Gutenberg PR
WordPress/gutenberg#77226 1:1.

flags @automattic/number-formatters as a script-module exporter
via wpScriptModuleExports so consumers can externalize it.
configures @automattic/number-formatters as a named packageSource
and demonstrates both import modes in the dashboard route:
static import for formatNumber, dynamic import for formatNumberCompact
via React.lazy and Suspense.
@retrofox retrofox force-pushed the update/wp-build-package-sources branch from 25c7409 to 1b3fb87 Compare April 17, 2026 16:00
@retrofox retrofox requested a review from anomiex April 17, 2026 16:10
regenerate patch against 0.12.0 sources using upstream PR #77226 diff.
header embeds the version-agnostic rebase procedure.
# Conflicts:
#	pnpm-lock.yaml
#	projects/packages/premium-analytics/package.json
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.

3 participants