Repository navigation
Webpack config: replace the duplicated @wordpress/ui bundling block with an opt-in option - #52207
Conversation
…ed default Three webpack configs each carried the same `DependencyExtractionPlugin` override for `@wordpress/theme` and `@wordpress/private-apis`, with the rationale written out four times. The rule now lives once in `defaultRequestMap`, which merges under every caller's own `requestMap`. The Jetpack plugin's AI admin and email design editor entries opt `@wordpress/private-apis` back out with an empty entry: both unlock private APIs exposed by external WordPress packages, so their consent map has to stay external. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
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:
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:
If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack. Boost 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. Protect 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. |
Code Coverage SummaryCoverage changed in 1 file.
|
anomiex
left a comment
There was a problem hiding this comment.
I'd much rather we get rid of the theme bundling entirely, and polyfill where necessary instead. IMO bundling was the wrong decision in the first place, and then people copied it into these other places.
For that matter, we might also benefit from going further and providing handles like jetpack-wp-ui-0-22-1 and jetpack-wp-dataviews-18-1-0 to provide the versions we use of those shared components, instead of including them in dozens of bundles. Although getting wp-build to use those would likely be a pain.
| '@wordpress/global-styles-engine': { external: false }, | ||
| // Opts out of the shared default: the editor packages this entry unlocks | ||
| // private APIs from are external, so their consent map has to be too. | ||
| '@wordpress/private-apis': {}, |
…s option The earlier approach added @wordpress/theme and @wordpress/private-apis to defaultRequestMap. That changed every consumer: it broke the packages/jetpack-mu-wpcom build, broke three packages/wp-build-polyfills tests, needed two opt-outs inside the Jetpack plugin config, and grew two bundles. DependencyExtractionPlugin now takes bundleWpUiDeps, off by default, so nothing changes unless a call site asks. The four call sites that carried the nine-line requestMap block verbatim now set the flag instead. jetpack-ai-admin keeps its own requestMap, because it bundles @wordpress/theme alone. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx
dhasilva
left a comment
There was a problem hiding this comment.
Thanks for the follow-up. The mechanics are correct:
bundleWpUiDepsdefaults tofalseand is pulled out of the options before they reach DEWP.- A caller's
requestMapstill takes priority. - The byte-identical build diff is the right acceptance test.
The problem is the rationale this PR makes canonical. Both halves are false at this SHA (details inline on src/webpack.js). That also affects the direction question in anomiex's review: at the WP 7.0 floor, the original reason for bundling @wordpress/theme no longer applies.
A correction to my own comment on #52160: I called bundling the pair jointly "load-bearing". It is, but only in one direction, and I should have checked which.
- [blocker] The stated rationale is wrong at this SHA: the
wpUiRequestMapcomment, the JSDoc, the README and the Jetpack call site. - [suggestion] Give the webpack-config changelog a real
addedentry.
Generated by Claude.
| // @wordpress/ui pulls these in transitively; externalizing them targets script handles many pages | ||
| // never register, so the whole bundle fails to enqueue. Bundle the pair jointly — split, the | ||
| // module-scope lock() in @wordpress/theme and the per-instance consent map in | ||
| // @wordpress/private-apis diverge at runtime. See PR #48173. |
There was a problem hiding this comment.
[blocker] Both halves of this rationale are false at this SHA. The JSDoc below, the README and the Jetpack call site all repeat it.
"Script handles many pages never register, so the whole bundle fails to enqueue."
- Jetpack (
JETPACK__MINIMUM_WP_VERSION, since General: Update minimum WordPress version to 7.0 #51370), Boost, Protect and Search all require WP 7.0. - WP 7.0 core registers
wp-theme. Core'sprivate-apisallowlist includes@wordpress/themeand@wordpress/ui. I checked 7.0-beta1 and 7.1 core; 6.9 has neither.wp-private-apishas been registered since 6.2. - Script handles are registered globally, not per page. "A page that registers neither handle" isn't a state a supported site can be in.
"Split, the lock() and the consent map diverge at runtime. See PR #48173."
- Components: Migrate remaining Notice consumers to @wordpress/ui #48173 merged no webpack change. Its description says "
@wordpress/private-apisstays externalized in this PR". The failure it describes is core's allowlist rejecting theme's opt-in, which can't happen on 7.0. Joint bundling started in Boost: Migrate Notice to @wordpress/ui #48171 (Boost). - Only one direction breaks: bundling
@wordpress/private-apiswhile@wordpress/themestays external. That throws "Cannot unlock an object that was not locked before", the wp-build-polyfills failure quoted in the PR description. - The other direction works.
jetpack-ai-adminhas bundled theme with private-apis external on purpose since AI Hub: add Scheduled tasks management #51319 (webpack.config.js#L255-L263). This comment's claim that any split breaks contradicts that entry.
I haven't checked whether using core 7.0's wp-theme works at runtime. The open question is whether it's too old for the bundled @wordpress/ui, which is what a polyfill would solve. So the direction question in anomiex's review should be settled first.
If the option stays:
- State the real current reason. If it's that version mismatch, say so.
- Keep only the direction-specific gotcha here, e.g.
// Never bundle @wordpress/private-apis without @wordpress/theme: theme would lock on core's consent map and the bundled unlock() throws. - Keep the when-to-use on the
@paramonly. - Point at Boost: Migrate Notice to @wordpress/ui #48171, or drop the PR number.
Generated by Claude.
| Two additional options are recognized: | ||
|
|
||
| - `requestMap`: An easier way to specify additional dependencies to extract, rather than redefining `requestToHandle` and `requestToExternal`. Key is the dependency, value is an object with `handle` and `external` keys corresponding to the return values of `requestToHandle` and `requestToExternal`. | ||
| - `bundleWpUiDeps`: Bundle `@wordpress/theme` and `@wordpress/private-apis` instead of externalizing them to the `wp-theme` and `wp-private-apis` script handles. Defaults to `false`. Set it to `true` on an entry that renders `@wordpress/ui` on a page that registers neither handle, otherwise the whole bundle fails to enqueue. The pair is bundled jointly on purpose: see [#48173](https://github.com/Automattic/jetpack/pull/48173). Your own `requestMap` still wins over it. |
There was a problem hiding this comment.
[blocker] Same finding as on src/webpack.js:
- "A page that registers neither handle" can't happen at the WP 7.0 floor.
- Components: Migrate remaining Notice consumers to @wordpress/ui #48173 didn't bundle the pair; joint bundling started in Boost: Migrate Notice to @wordpress/ui #48171.
This line should match whatever that thread settles on.
Generated by Claude.
| // The licensing activation screen pulls in @wordpress/ui, and this page | ||
| // registers neither handle: WP < 7.0 has no core wp-theme, and the | ||
| // wp-build-polyfills shim is not loaded here. |
There was a problem hiding this comment.
[blocker] Same finding as on src/webpack.js. Jetpack's minimum has been WP 7.0 since #51370, and 7.0 core registers wp-theme. "WP < 7.0 has no core wp-theme" therefore describes a version Jetpack no longer supports. If this call site keeps a comment, it should give this entry's own current reason for opting in.
Generated by Claude.
| Significance: patch | ||
| Type: changed | ||
| Comment: Replace the duplicated DependencyExtractionPlugin requestMap block with an opt-in bundleWpUiDeps option. No build output changes. | ||
|
|
||
|
|
There was a problem hiding this comment.
[suggestion] This package gains a public option. Every earlier addition is recorded under ### Added at minor significance:
PnpmDeterministicChunkIdsin 4.1.0 (webpack-config: Add PnpmDeterministicChunkIds plugin #50758)- the cache function in 3.10.0 (Webpack: opt-in filesystem cache + stop wiping
.cache/on clean #49174) BundledWpPkgsTranspileRulesin 3.8.0 (Footer update #47840)
With an empty entry, its CHANGELOG will never mention bundleWpUiDeps. The four consumer entries are right as they are.
| Significance: patch | |
| Type: changed | |
| Comment: Replace the duplicated DependencyExtractionPlugin requestMap block with an opt-in bundleWpUiDeps option. No build output changes. | |
| Significance: minor | |
| Type: added | |
| DependencyExtractionPlugin: Add a `bundleWpUiDeps` option to bundle `@wordpress/theme` and `@wordpress/private-apis`. |
Generated by Claude.
The comments, README and Jetpack call site said the wp-theme and wp-private-apis handles are missing on many pages, and cited #48173. Neither holds at the WP 7.0 minimum: core registers both handles, and #48173 merged no webpack change. State the lock rule instead: a bundled @wordpress/private-apis unlocks only what its own bundle locked. State the current reason to use the option: @wordpress/ui is built against a newer @wordpress/theme than core's wp-theme. Record the new option as an added changelog entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RnmaaEamjHo2MmDpnrwiNa
|
Agreed. Fixed in e84a008:
On your open question, from the code only (not tested at runtime): WP 7.0.4's @anomiex Could we push unbundling theme out of the scope of this? This PR does not change what gets bundled. It only removes the copies. Before we stop bundling Our bundles use
Unbundling means these screens run on whatever
That is about 180 runs, before screen states. Each run checks that the script enqueues, the console has no errors, and the screenshots match the current build. Based on previous experiences messing with theme/ui/tokens/polyfill, I'd rather we don't rely only on theory, and running all these combinations would fit better on a separate, validating PR. |
|
I'd rather we don't make it easier to do the wrong thing by putting the wrong thing into the webpack-config package. To use a metaphor, let's leave the turd unpolished and work on cleaning it up instead.
I think it can, if it's activated for the page in question. Where that can get tricky is in editor blocks. |
Fixes #
Proposed changes
Follow-up to the review on #52160, which was about to add a fourth copy of the same
DependencyExtractionPluginoverride.Four webpack configs repeat the same nine-line block plus its rationale:
This PR replaces those four copies with one opt-in option on
DependencyExtractionPlugin:bundleWpUiDepstoprojects/js-packages/webpack-config/src/webpack.js. It defaults tofalse, so no existing consumer changes behaviour.requestMap, so an explicit per-request override still wins.@wordpress/private-apisunlocks only what its own bundle locked. So it must not be bundled while@wordpress/themestays external, or in an entry that unlocks private APIs of an externalwp-*script. Either way it throws "Cannot unlock an object that was not locked before".@wordpress/uiis built against a newer@wordpress/themethan core'swp-theme.admincall-site comment. It said WP < 7.0 has no corewp-theme, which no longer applies at the WP 7.0 minimum.Converted call sites:
projects/plugins/boost/webpack.config.jsbundleWpUiDeps: trueprojects/packages/search/tools/webpack.dashboard.config.jsbundleWpUiDeps: trueprojects/plugins/protect/webpack.config.jsbundleWpUiDeps: trueprojects/plugins/jetpack/tools/webpack.config.js,adminentry onlybundleWpUiDeps: trueLeft alone on purpose
jetpack-ai-adminin the Jetpack config bundles@wordpress/themealone and deliberately keeps@wordpress/private-apisexternal, so bundled DataViews can unlock private APIs on external@wordpress/components. A boolean cannot express that shape, so this entry keeps its ownrequestMap. It is the reason the option is not "always bundle both".email-design-editorin the same file has no override on trunk and gets none here.packages/wp-build-polyfillsandpackages/jetpack-mu-wpcom— untouched.@wordpress/themebundling, or the theme-only shape, needs runtime proof on every affected screen first. WP 7.0 core ships@wordpress/theme0.7.1, and these bundles use 2.0.0.Why the earlier
defaultRequestMapapproach was abandonedThe first version of this PR put both entries in
defaultRequestMap, flipping the default for every consumer of the shared config. That is recorded here because it is the most useful evidence on this PR. It failed in four ways:packages/jetpack-mu-wpcom's build outright.@automattic/components@3.0.3imports@wordpress/private-apiswithout declaring it as a dependency. Once webpack had to resolve the request instead of externalizing it, the build failed withModule not found. CI job: Install the Monorepo and build wpcomsh.packages/wp-build-polyfills— the package that exists to register these very handles. One failed with the literal messageCannot unlock an object that was not locked before, which is the split failure the rule above describes. CI jobs: JS tests and Code coverage (JS).projects/plugins/jetpack/tools/webpack.config.js(jetpack-ai-adminandemail-design-editor), written as magic empty entries ('@wordpress/private-apis': {}). Two opt-outs in the first plugin built is not a good sign for a default.packages/newsletterbuild/writing-prompt.jspackages/newsletterbuild/newsletter.jspackages/my-jetpackbuild/index.jsAn opt-in flag has none of those costs: it touches only the four entries that already had the block.
Related product discussion/links
jetpack-ai-adminkeeps@wordpress/private-apisexternal.Does this pull request change what data or activity we track or use?
No.
Testing instructions
This is a build-configuration change with no runtime UI. The acceptance test is zero change in build output. Everything below is what I ran.
For each of
plugins/boost,plugins/protect,packages/search,plugins/jetpackandpackages/jetpack-mu-wpcom, on trunk and on this branch, in separate worktrees:All ten builds exit 0.
packages/jetpack-mu-wpcombuilds again, which is failure 1 above resolved.diff -rthe build output directory of each project between trunk and this branch:*.asset.phpcomparedplugins/boostapp/assets/distplugins/protectbuildpackages/searchbuildplugins/jetpack_inc/buildpackages/jetpack-mu-wpcomsrc/buildSpot-check the two handles this PR is about, trunk vs branch:
wp-theme/wp-private-apison trunkboost/app/assets/dist/jetpack-boost.asset.phpprotect/build/index.asset.phpsearch/build/dashboard/jp-search-dashboard.asset.phpjetpack/_inc/build/admin.asset.phpjetpack/_inc/build/jetpack-ai-admin.asset.phpwp-private-apiswp-private-apisjetpack/_inc/build/email-design-editor.asset.phpwp-private-apiswp-private-apisjetpack-mu-wpcom/src/buildpnpm jetpack test js packages/wp-build-polyfills: passes, which is failure 2 above resolved.pnpm exec eslinton all six changed files: clean.Not run: no browser check of any admin page. Build output is byte-identical everywhere, so there is nothing new to click through.
🤖 Generated with Claude Code
https://claude.ai/code/session_01SWVs5oUDimen1FeGJhJAkx