Skip to content

Dependency extraction webpack plugin: use package.json wpScript value to determine bundling - #79945

Open
simison wants to merge 7 commits into
trunkfrom
update/package-json-defined-externalization
Open

Dependency extraction webpack plugin: use package.json wpScript value to determine bundling#79945
simison wants to merge 7 commits into
trunkfrom
update/package-json-defined-externalization

Conversation

@simison

@simison simison commented Jul 7, 2026

Copy link
Copy Markdown
Member

What?

Follow-up to convo at

Replaces the hardcoded BUNDLED_PACKAGES list in @wordpress/dependency-extraction-webpack-plugin with package metadata (wpScript: false) as the source of truth for bundled packages.

When wpScript is true or missing, the package gets externalised. Thus, one needs to specifically opt-in to bundling just like previously with BUNDLED_PACKAGES, or use Webpack configs like these:

DependencyExtractionPlugin: {
	requestMap: {
		'@wordpress/theme': { external: false },
	},
},
  • Updates the changelog workflow to treat @wordpress/undo-manager as externalized (it was incorrectly bundled before, see notes).

  • Adds wpScript: false to the legacy bundled packages that lacked it.

  • Keeps existing wpScript: false in @wordpress/widget-dashboard and @wordpress/widget-primitives; these were not listed in BUNDLED_PACKAGES previously but are now effectively bundled. They're pretty new experimental packages, so I'm assuming we want to keep bundling them?

Why?

BUNDLED_PACKAGES duplicated logic that wp-build already derives from package.json, so the two bundlers could drift. We already had a concrete example: @wordpress/undo-manager was listed as bundled in dependency-extraction, but wp-build externalizes it because it has wpScript: true.

Using wpScript: false makes bundling explicit and keeps webpack (@wordpress/scripts) and esbuild (wp-build) aligned on the same rule: packages are bundled only when they opt out of WordPress script registration.

How?

I'm mostly duplicating the logic from WP Build to the Dependency Extraction plugin: I could make one depend on another or move the utils to yet another shared package, but since these are just script tools, it felt like copying is fine. (Also, @wordpress/build is ESM + Node >=20.10, while dependency-extraction supports Node >=18.12 and is CJS.)

I added wpScript: false to packages we're continuing to bundle.

Testing Instructions

  • npm run test:unit packages/dependency-extraction-webpack-plugin/test/util.js
  • Confirm bundled set is unchanged except:
    • @wordpress/undo-manager, which is now externalised.
    • @wordpress/widget-dashboard, which is now bundled (already had wpScript: false).
    • @wordpress/widget-primitives , which is now bundled (already had wpScript: false).

Use of AI Tools

yes

@simison
simison requested review from aduth, retrofox and youknowriad July 7, 2026 13:39
@simison simison added the [Tool] Dependency Extraction Webpack Plugin /packages/dependency-extraction-webpack-plugin label Jul 7, 2026
@github-actions

This comment was marked as resolved.

@github-actions

github-actions Bot commented Jul 7, 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: simison <simison@git.wordpress.org>
Co-authored-by: aduth <aduth@git.wordpress.org>
Co-authored-by: manzoorwanijk <manzoorwanijk@git.wordpress.org>
Co-authored-by: anomiex <bjorsch@git.wordpress.org>

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

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Size Change: 0 B

Total Size: 7.67 MB

compressed-size-action

@simison

simison commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

Keeps existing wpScript: false in @wordpress/widget-dashboard and @wordpress/widget-primitives; these were not listed in BUNDLED_PACKAGES previously but are now effectively bundled. They're pretty new experimental packages, so I'm assuming we want to keep bundling them?

@retrofox could you confirm if we want to bundle these packages? That helps to do bigger API changes for now, rather than externalizing to Gutenberg via wp.* global.

@simison simison added the [Type] Build Tooling Issues or PRs related to build tooling label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Flaky tests detected in 7236183.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/28872527954
📝 Reported issues:

Copilot AI left a comment

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.

Pull request overview

Updates @wordpress/dependency-extraction-webpack-plugin to determine which @wordpress/* packages should remain bundled based on each package’s package.json metadata (wpScript: false), replacing the previous hardcoded BUNDLED_PACKAGES list. This aligns dependency extraction behavior with wp-build and updates affected packages/workflows accordingly.

Changes:

  • Replace the hardcoded bundled list with runtime resolution of wpScript from each package’s package.json.
  • Add wpScript: false (and changelog entries) to legacy bundled packages that lacked it.
  • Update the changelog-check workflow list to treat @wordpress/undo-manager as externalized and include widget packages.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/views/package.json Marks @wordpress/views as bundled via wpScript: false.
packages/views/CHANGELOG.md Documents the wpScript: false metadata change.
packages/style-runtime/package.json Marks @wordpress/style-runtime as bundled via wpScript: false.
packages/style-runtime/CHANGELOG.md Documents the wpScript: false metadata change.
packages/interface/package.json Marks @wordpress/interface as bundled via wpScript: false.
packages/interface/CHANGELOG.md Documents the wpScript: false metadata change.
packages/icons/package.json Marks @wordpress/icons as bundled via wpScript: false.
packages/icons/CHANGELOG.md Documents the wpScript: false metadata change.
packages/fields/package.json Marks @wordpress/fields as bundled via wpScript: false.
packages/fields/CHANGELOG.md Documents the wpScript: false metadata change.
packages/dataviews/package.json Marks @wordpress/dataviews as bundled via wpScript: false.
packages/dataviews/CHANGELOG.md Documents the wpScript: false metadata change.
packages/admin-ui/package.json Marks @wordpress/admin-ui as bundled via wpScript: false.
packages/admin-ui/CHANGELOG.md Documents the wpScript: false metadata change.
packages/dependency-extraction-webpack-plugin/lib/util.js Implements bundled detection by reading wpScript from resolved package.json.
packages/dependency-extraction-webpack-plugin/test/util.js Adds tests for bundled vs externalized behavior based on wpScript.
packages/dependency-extraction-webpack-plugin/CHANGELOG.md Notes the change from hardcoded list to wpScript: false metadata.
.github/workflows/check-package-changelogs.yml Updates the workflow package list to match the new bundling/externalization set.
Comments suppressed due to low confidence (1)

packages/dependency-extraction-webpack-plugin/lib/util.js:182

  • isBundledPackageForScripts() runs before the @wordpress/ namespace check, so scoped non-WordPress imports (e.g. @foo/bar) will still trigger require.resolve(<pkg>/package.json) and JSON parsing even though they can never be externalized here; this can add unnecessary I/O during builds.
	if ( isBundledPackageForScripts( request ) ) {
		return undefined;
	}

	if ( request.startsWith( WORDPRESS_NAMESPACE ) ) {

*/
function findPackageRoot( startDir ) {
let current = startDir;
const root = path.parse( current ).root;

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.

Is there a more reasonable stopping point we should stop at, like cwd or project root somehow, rather than filesystem root? I suppose in practice this isn't much of an actual concern.

* @param {string|null} resolveDir Optional directory context for resolution.
* @return {{wpScript?: boolean, wpScriptModuleExports?: string|Object}|null} Package metadata when resolvable.
*/
function getPackageInfo( fullPackageName, resolveDir = null ) {

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.

There's a lot here that repeats from what we have in @wordpress/build as well. As there, a lot of this will be simplified with findPackageJSON in newer versions of Node. We could always refactor later, but with recent almost-unblocking of #72973 (comment), we could also consider to wait? Not sure how much that helps simplify this code.

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.

Toward simplifying the shared code, I wonder if there's libraries that help or if we should create our own. Some combination of resolve-pkg, read-pkg, and/or find-up for example.

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.

We could use the approach that we used in license check

function resolvePackagePath( packageName, fromDir ) {
// Use findPackageJSON when available (Node.js 22.14.0+)
if ( findPackageJSON ) {

},
"./package.json": "./package.json"
},
"wpScript": false,

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.

I can appreciate the explicitness, but do we need these explicit false values? Or just lean on this being an opt-in behavior that defaults to false ?

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.

IMHO, this explicitness is good, but I think the extraction plugin should not expect the property to be explicitly set to false.

Comment thread packages/dependency-extraction-webpack-plugin/lib/util.js Outdated
@manzoorwanijk

manzoorwanijk commented Jul 16, 2026

Copy link
Copy Markdown
Member

Heads up on a downstream compatibility concern from Jetpack. CC: @anomiex

I asked Claude to see how this can affect Jetpack monorepo:

Jetpack consumes this plugin via @automattic/jetpack-webpack-config, and its requestToExternal returns undefined for anything outside our own request map — so the default bundling logic applies across every webpack-built Jetpack project.

The issue is that the plugin version and the package versions don't necessarily move together outside this monorepo. Our lockfile currently has DEWP 6.50.0 alongside @wordpress/icons@15.1.0, dataviews@17.1.0, fields@0.42.0, interface@9.35.0, admin-ui@2.5.0, style-runtime@0.5.0, and views@1.17.0 — none of which carry wpScript yet. If DEWP updates ahead of those (which our Renovate grouping makes likely, since they're in separate groups), each of them silently flips from bundled to a wp.icons / wp-icons external that WordPress never registers. That fails at runtime rather than at build time, so it's unlikely to be caught by CI.

The reverse order is harmless — packages gaining wpScript: false under the old plugin still match BUNDLED_PACKAGES.

Would it be possible to bump the peer/minimum versions of the affected packages in @wordpress/scripts, or otherwise document a minimum version, so the metadata the plugin now reads is guaranteed to be present? Failing open to "externalize" on a missing field is the risky default for consumers pinning versions independently.

Separately: is there a stable replacement for the BUNDLED_PACKAGES list as a reference? We link to it from our Renovate config to keep our bundled-package group in sync, and that anchor goes away with this change.

@anomiex

anomiex commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

The issue is that the plugin version and the package versions don't necessarily move together outside this monorepo.

It gets even worse if you consider sub-dependencies. We still have @wordpress/icons@10.32.0 in one dependency chain, which has just today finally had a (hopefully) usable release with a fix for the breaking changes in icons v11.

Co-authored-by: Manzoor Wani <manzoorwani.jk@gmail.com>
@simison

simison commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

is there a stable replacement for the BUNDLED_PACKAGES list as a reference? We link to it from our Renovate config to keep our bundled-package group in sync, and that anchor goes away with this change.

I think it would be useful for all sorts of reasons to document somewhere, so might need generating somehow.

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

Labels

[Package] DataViews /packages/dataviews [Package] Fields /packages/fields [Package] Icons /packages/icons [Package] Interface /packages/interface [Tool] Dependency Extraction Webpack Plugin /packages/dependency-extraction-webpack-plugin [Type] Build Tooling Issues or PRs related to build tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants