@wordpress/build 0.7.1-next.v.202602091733.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.8.0 (2026-02-18)
6
+
5
7
  ## 0.7.0 (2026-01-29)
6
8
 
7
9
  - Update documentation to describe `wpPlugin.name`
package/README.md CHANGED
@@ -132,6 +132,42 @@ Files to copy with optional PHP transformations:
132
132
  }
133
133
  ```
134
134
 
135
+ ### `wpWorkers`
136
+
137
+ Worker bundle definitions for packages that need self-contained Web Worker files.
138
+ Workers are bundled with all dependencies included and can be loaded via Blob URLs.
139
+
140
+ **String shorthand** — entry path only:
141
+
142
+ ```json
143
+ {
144
+ "wpWorkers": {
145
+ "./worker": "./src/worker.ts"
146
+ }
147
+ }
148
+ ```
149
+
150
+ **Object format** — entry path with module resolve redirects:
151
+
152
+ ```json
153
+ {
154
+ "wpWorkers": {
155
+ "./worker": {
156
+ "entry": "./src/worker.ts",
157
+ "resolve": {
158
+ "vips-es6.js": "vips.js"
159
+ }
160
+ }
161
+ }
162
+ }
163
+ ```
164
+
165
+ The `resolve` map redirects module loads during bundling. Keys are filename
166
+ patterns to match; values are replacement filenames in the same directory.
167
+ This is useful when a dependency's ES module entry point uses `import.meta.url`,
168
+ which fails in Blob URL Worker contexts. By redirecting to an alternative
169
+ entry point (e.g., a CommonJS version), the issue is avoided.
170
+
135
171
  ## Root Configuration
136
172
 
137
173
  Configure your root `package.json` with a `wpPlugin` object to control global namespace and externalization behavior:
@@ -14,6 +14,92 @@ import { readFile, writeFile, access } from 'fs/promises';
14
14
  import path from 'path';
15
15
  import esbuild from 'esbuild';
16
16
 
17
+ /**
18
+ * Creates an esbuild plugin that redirects module loads based on filename patterns.
19
+ *
20
+ * This is useful when bundling workers for Blob URL contexts where certain
21
+ * ES module entry points use `import.meta.url` (which resolves to an invalid
22
+ * `blob:` URL at runtime). By redirecting to an alternative entry point
23
+ * (e.g., a CommonJS version), the issue is avoided.
24
+ *
25
+ * Packages declare redirects in their `wpWorkers` config:
26
+ *
27
+ * "wpWorkers": {
28
+ * "./worker": {
29
+ * "entry": "./src/worker.ts",
30
+ * "resolve": {
31
+ * "vips-es6.js": "vips.js"
32
+ * }
33
+ * }
34
+ * }
35
+ *
36
+ * @param {Object} resolveMap An object mapping source filenames to target
37
+ * filenames. When esbuild loads a file whose path
38
+ * ends with a source key, the plugin rewrites it
39
+ * to re-export from the corresponding target file
40
+ * in the same directory.
41
+ * @return {Object} An esbuild plugin.
42
+ */
43
+ function createModuleRedirectPlugin( resolveMap ) {
44
+ // Build a single regex that matches any of the source filenames.
45
+ const escapedKeys = Object.keys( resolveMap ).map( ( key ) =>
46
+ key.replace( /[.*+?^${}()|[\]\\]/g, '\\$&' )
47
+ );
48
+ const pattern = new RegExp( `(${ escapedKeys.join( '|' ) })$` );
49
+
50
+ return {
51
+ name: 'module-redirect',
52
+ setup( build ) {
53
+ build.onLoad( { filter: pattern }, ( args ) => {
54
+ // Find which key matched.
55
+ const matchedKey = Object.keys( resolveMap ).find( ( key ) =>
56
+ args.path.endsWith( key )
57
+ );
58
+ const targetPath = args.path.replace(
59
+ matchedKey,
60
+ resolveMap[ matchedKey ]
61
+ );
62
+ return {
63
+ contents: `export { default } from ${ JSON.stringify(
64
+ targetPath
65
+ ) };`,
66
+ loader: 'js',
67
+ };
68
+ } );
69
+ },
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Extracts the entry path from a wpWorkers config value.
75
+ *
76
+ * Supports both the string shorthand and the object format:
77
+ * - String: "./src/worker.ts"
78
+ * - Object: { "entry": "./src/worker.ts", "resolve": { ... } }
79
+ *
80
+ * @param {string|Object} workerConfig The worker configuration value.
81
+ * @return {string} The entry file path.
82
+ */
83
+ function getWorkerEntryPath( workerConfig ) {
84
+ if ( typeof workerConfig === 'string' ) {
85
+ return workerConfig;
86
+ }
87
+ return workerConfig.entry;
88
+ }
89
+
90
+ /**
91
+ * Extracts the resolve map from a wpWorkers config value, if present.
92
+ *
93
+ * @param {string|Object} workerConfig The worker configuration value.
94
+ * @return {Object|undefined} The resolve map, or undefined if not configured.
95
+ */
96
+ function getWorkerResolveMap( workerConfig ) {
97
+ if ( typeof workerConfig === 'string' ) {
98
+ return undefined;
99
+ }
100
+ return workerConfig.resolve;
101
+ }
102
+
17
103
  /**
18
104
  * Generate placeholder worker-code.ts for packages with wpWorkers.
19
105
  *
@@ -78,7 +164,9 @@ export async function buildWorkers(
78
164
  ? Object.entries( packageJson.wpWorkers )
79
165
  : [];
80
166
 
81
- for ( const [ outputName, entryPath ] of workerEntries ) {
167
+ for ( const [ outputName, workerConfig ] of workerEntries ) {
168
+ const entryPath = getWorkerEntryPath( workerConfig );
169
+ const resolveMap = getWorkerResolveMap( workerConfig );
82
170
  const workerEntryPoint = path.join( packageDir, entryPath );
83
171
  const workerOutputName = outputName.replace( /^\.\//, '' );
84
172
 
@@ -98,7 +186,12 @@ export async function buildWorkers(
98
186
  sourcemap: true,
99
187
  // Bundle everything - workers need to be self-contained.
100
188
  external: [],
101
- plugins: [ wasmInlinePlugin ],
189
+ plugins: [
190
+ wasmInlinePlugin,
191
+ ...( resolveMap
192
+ ? [ createModuleRedirectPlugin( resolveMap ) ]
193
+ : [] ),
194
+ ],
102
195
  define: {
103
196
  'process.env.NODE_ENV': JSON.stringify(
104
197
  process.env.NODE_ENV || 'production'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/build",
3
- "version": "0.7.1-next.v.202602091733.0+daa0b19c4",
3
+ "version": "0.8.0",
4
4
  "description": "Build tool for WordPress plugins.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -77,5 +77,5 @@
77
77
  "publishConfig": {
78
78
  "access": "public"
79
79
  },
80
- "gitHead": "74f59922b25e30904319373dda91bf8e81f3544e"
80
+ "gitHead": "376124aa10dbc2cc0c81c964ec00b99fcfee5382"
81
81
  }
@@ -96,8 +96,9 @@ if ( ! function_exists( '{{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}_wp_admin_preload_da
96
96
  */
97
97
  function {{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}_wp_admin_preload_data() {
98
98
  // Define paths to preload - same for all pages
99
+ // Please also change packages/core-data/src/entities.js when changing this.
99
100
  $preload_paths = array(
100
- '/?_fields=description,gmt_offset,home,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
101
+ '/?_fields=description,gmt_offset,home,image_sizes,image_size_threshold,image_output_formats,jpeg_interlaced,png_interlaced,gif_interlaced,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
101
102
  array( '/wp/v2/settings', 'OPTIONS' ),
102
103
  );
103
104
 
@@ -97,8 +97,9 @@ if ( ! function_exists( '{{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}_preload_data' ) ) {
97
97
  */
98
98
  function {{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}_preload_data() {
99
99
  // Define paths to preload - same for all pages
100
+ // Please also change packages/core-data/src/entities.js when changing this.
100
101
  $preload_paths = array(
101
- '/?_fields=description,gmt_offset,home,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
102
+ '/?_fields=description,gmt_offset,home,image_sizes,image_size_threshold,image_output_formats,jpeg_interlaced,png_interlaced,gif_interlaced,name,site_icon,site_icon_url,site_logo,timezone_string,url,page_for_posts,page_on_front,show_on_front',
102
103
  array( '/wp/v2/settings', 'OPTIONS' ),
103
104
  );
104
105