Skip to content

Conversation

@youknowriad
Copy link
Contributor

@youknowriad youknowriad commented Jan 5, 2026

Note This is fully vibe-coded with my own instructions about how it should be API wise. I also didn't test it yet.

Summary

Adds support for building vendor packages (like React) directly from node_modules instead of relying on pre-built UMD bundles. This addresses the React 19 upgrade blocker where UMD builds are no longer shipped.

Changes

  • New vendorScripts config in wpPlugin (package.json)
  • bundleVendorScript() function that bundles packages from node_modules into IIFE format
  • Updated wordpress-externals-plugin to accept vendor scripts config while preserving defaults for third-party plugins

Configuration

"vendorScripts": [
  { "name": "react", "global": "React", "handle": "react" },
  { "name": "react-dom", "global": "ReactDOM", "handle": "react-dom", "dependencies": ["react"] },
  { "name": "react/jsx-runtime", "global": "ReactJSXRuntime", "handle": "react-jsx-runtime", "dependencies": ["react"] }
]

Build Output

build/scripts/react/index.min.js (~7KB) - exposes window.React
build/scripts/react-dom/index.min.js (~135KB) - exposes window.ReactDOM
build/scripts/react-jsx-runtime/index.min.js (~1KB) - exposes window.ReactJSXRuntime

Test plan

Build completes successfully with npm run build
Vendor scripts are bundled and registered in build/scripts/index.php
Asset files have correct dependencies
Test in browser that React globals are exposed correctly

Adds support for building vendor packages (like React) from node_modules
instead of relying on pre-built UMD bundles. This is needed for React 19+
which no longer ships UMD builds.

New `vendorScripts` config in `wpPlugin`:
- `name`: Package name (e.g., 'react', 'react/jsx-runtime')
- `global`: Global variable name (e.g., 'React', 'ReactJSXRuntime')
- `handle`: WordPress script handle (e.g., 'react', 'react-jsx-runtime')
- `dependencies`: Array of dependency handles

The bundleVendorScript function:
- Resolves packages from node_modules using require.resolve()
- Builds IIFE bundles with proper globalName
- Externalizes other vendor packages to avoid duplication
- Generates .asset.php files with dependencies and version hash

Default vendor externals are preserved in wordpress-externals-plugin for
third-party plugins that rely on WordPress core providing these scripts.
@youknowriad youknowriad requested review from jsnajdr and tyxla January 5, 2026 11:34
@youknowriad youknowriad added the [Type] Build Tooling Issues or PRs related to build tooling label Jan 5, 2026
@Mamaduka
Copy link
Member

Mamaduka commented Jan 7, 2026

I think the script bundles latest version of the scripts is causing the CI failures.

} = config;

const { createRequire } = await import( 'module' );
const require = createRequire( import.meta.url );
Copy link
Member

Choose a reason for hiding this comment

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

Instead of resolving the package ourselves, we could tell esbuild to do it for us. Just tell it to bundle this synthetic module:

export * from 'react';

where react is the ${name} value. With the iife format and globalName set to React, it will produce a script that assigns all react exports to the React global. Exactly what we want.

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

Labels

[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