@wordpress/build 0.7.1-next.v.0 → 0.7.1-next.v.202602091733.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 +2 -0
- package/lib/build.mjs +76 -0
- package/lib/worker-build.mjs +265 -0
- package/package.json +3 -3
- package/tsconfig.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
## 0.7.0 (2026-01-29)
|
|
6
6
|
|
|
7
7
|
- Update documentation to describe `wpPlugin.name`
|
|
8
|
+
- Add `wpWorkers` field support for automatic worker bundling ([#74785](https://github.com/WordPress/gutenberg/pull/74785)).
|
|
9
|
+
- Add WASM inlining plugin for bundling WebAssembly modules.
|
|
8
10
|
|
|
9
11
|
## 0.6.0 (2026-01-16)
|
|
10
12
|
|
package/lib/build.mjs
CHANGED
|
@@ -42,6 +42,11 @@ import {
|
|
|
42
42
|
getRouteMetadata,
|
|
43
43
|
generateContentEntryPoint,
|
|
44
44
|
} from './route-utils.mjs';
|
|
45
|
+
import {
|
|
46
|
+
generateWorkerPlaceholder,
|
|
47
|
+
buildWorkers,
|
|
48
|
+
generateWorkerCode,
|
|
49
|
+
} from './worker-build.mjs';
|
|
45
50
|
|
|
46
51
|
const ROOT_DIR = process.cwd();
|
|
47
52
|
const PACKAGES_DIR = path.join( ROOT_DIR, 'packages' );
|
|
@@ -219,6 +224,53 @@ function createStyleBundlingPlugins( workingDir ) {
|
|
|
219
224
|
];
|
|
220
225
|
}
|
|
221
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Plugin to inline WASM files as base64 data URLs.
|
|
229
|
+
* This eliminates the need for separate WASM file downloads and avoids
|
|
230
|
+
* issues with hosts not serving WASM files with the correct MIME type.
|
|
231
|
+
*
|
|
232
|
+
* @return {Object} esbuild plugin.
|
|
233
|
+
*/
|
|
234
|
+
const wasmInlinePlugin = {
|
|
235
|
+
name: 'wasm-inline',
|
|
236
|
+
setup( build ) {
|
|
237
|
+
// Resolve .wasm imports from node_modules.
|
|
238
|
+
build.onResolve( { filter: /\.wasm$/ }, async ( args ) => {
|
|
239
|
+
// Handle imports like 'wasm-vips/vips.wasm'.
|
|
240
|
+
if ( ! args.path.startsWith( '.' ) ) {
|
|
241
|
+
const { createRequire } = await import( 'module' );
|
|
242
|
+
const require = createRequire( args.resolveDir + '/index.js' );
|
|
243
|
+
try {
|
|
244
|
+
const resolved = require.resolve( args.path );
|
|
245
|
+
return {
|
|
246
|
+
path: resolved,
|
|
247
|
+
namespace: 'wasm-inline',
|
|
248
|
+
};
|
|
249
|
+
} catch {
|
|
250
|
+
// If resolution fails, let other plugins handle it.
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
} );
|
|
256
|
+
|
|
257
|
+
// Load WASM files and convert to base64 data URLs.
|
|
258
|
+
build.onLoad(
|
|
259
|
+
{ filter: /.*/, namespace: 'wasm-inline' },
|
|
260
|
+
async ( args ) => {
|
|
261
|
+
const wasmBuffer = await readFile( args.path );
|
|
262
|
+
const base64 = wasmBuffer.toString( 'base64' );
|
|
263
|
+
const dataUrl = `data:application/wasm;base64,${ base64 }`;
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
contents: `export default "${ dataUrl }";`,
|
|
267
|
+
loader: 'js',
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
|
|
222
274
|
/**
|
|
223
275
|
* Normalize path separators for cross-platform compatibility.
|
|
224
276
|
*
|
|
@@ -1112,6 +1164,11 @@ async function transpilePackage( packageName ) {
|
|
|
1112
1164
|
|
|
1113
1165
|
const builds = [];
|
|
1114
1166
|
|
|
1167
|
+
// Generate placeholder worker-code.ts if this package has wpWorkers defined
|
|
1168
|
+
// and the file doesn't exist yet. This is needed because transpilation happens
|
|
1169
|
+
// before worker bundling, but vips-worker.ts imports from worker-code.ts.
|
|
1170
|
+
await generateWorkerPlaceholder( packageDir, packageJson );
|
|
1171
|
+
|
|
1115
1172
|
// Check if this is the components package that needs emotion babel plugin.
|
|
1116
1173
|
// Ideally we should remove this exception and move away from emotion.
|
|
1117
1174
|
const needsEmotionPlugin = packageName === 'components';
|
|
@@ -1186,6 +1243,7 @@ async function transpilePackage( packageName ) {
|
|
|
1186
1243
|
};
|
|
1187
1244
|
const plugins = [
|
|
1188
1245
|
needsEmotionPlugin && emotionPlugin,
|
|
1246
|
+
wasmInlinePlugin,
|
|
1189
1247
|
externalizeAllExceptCssPlugin,
|
|
1190
1248
|
...createStyleBundlingPlugins( packageDir ),
|
|
1191
1249
|
].filter( Boolean );
|
|
@@ -1254,6 +1312,24 @@ async function transpilePackage( packageName ) {
|
|
|
1254
1312
|
|
|
1255
1313
|
await Promise.all( builds );
|
|
1256
1314
|
|
|
1315
|
+
// Build workers if wpWorkers is defined in package.json.
|
|
1316
|
+
// Workers are bundled as self-contained files with all dependencies included.
|
|
1317
|
+
await buildWorkers( packageDir, packageJson, {
|
|
1318
|
+
buildDir,
|
|
1319
|
+
buildModuleDir,
|
|
1320
|
+
target,
|
|
1321
|
+
wasmInlinePlugin,
|
|
1322
|
+
} );
|
|
1323
|
+
|
|
1324
|
+
// Generate inline worker code exports and re-transpile worker-code.ts.
|
|
1325
|
+
await generateWorkerCode( packageDir, packageName, packageJson, {
|
|
1326
|
+
srcDir,
|
|
1327
|
+
buildDir,
|
|
1328
|
+
buildModuleDir,
|
|
1329
|
+
target,
|
|
1330
|
+
plugins,
|
|
1331
|
+
} );
|
|
1332
|
+
|
|
1257
1333
|
await compileStyles( packageName );
|
|
1258
1334
|
|
|
1259
1335
|
return Date.now() - startTime;
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker build utilities for wp-build.
|
|
3
|
+
*
|
|
4
|
+
* Handles building worker bundles and generating inline worker code
|
|
5
|
+
* for packages that define wpWorkers in their package.json.
|
|
6
|
+
*
|
|
7
|
+
* @package
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* External dependencies
|
|
12
|
+
*/
|
|
13
|
+
import { readFile, writeFile, access } from 'fs/promises';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import esbuild from 'esbuild';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate placeholder worker-code.ts for packages with wpWorkers.
|
|
19
|
+
*
|
|
20
|
+
* This must run before transpilation since worker files import worker-code.ts.
|
|
21
|
+
* The placeholder is later replaced with actual bundled worker content.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} packageDir Path to the package directory.
|
|
24
|
+
* @param {Object} packageJson Parsed package.json contents.
|
|
25
|
+
*/
|
|
26
|
+
export async function generateWorkerPlaceholder( packageDir, packageJson ) {
|
|
27
|
+
if ( ! packageJson.wpWorkers ) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const workerCodeFile = path.join( packageDir, 'src', 'worker-code.ts' );
|
|
32
|
+
try {
|
|
33
|
+
await access( workerCodeFile );
|
|
34
|
+
} catch {
|
|
35
|
+
// File doesn't exist, create placeholder
|
|
36
|
+
const placeholderContent = `/**
|
|
37
|
+
* Worker code for inline Blob URL creation.
|
|
38
|
+
*
|
|
39
|
+
* This file is a placeholder that gets overwritten by the build process.
|
|
40
|
+
* If you see this placeholder content at runtime, run \`npm run build\` first.
|
|
41
|
+
*
|
|
42
|
+
* @package gutenberg
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
46
|
+
export const workerCode = '/* Placeholder - run npm run build to generate actual worker code */';
|
|
47
|
+
`;
|
|
48
|
+
await writeFile( workerCodeFile, placeholderContent );
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Build worker bundles (ESM and CJS) for packages with wpWorkers.
|
|
54
|
+
*
|
|
55
|
+
* Workers are bundled as self-contained files with all dependencies included.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} packageDir Path to the package directory.
|
|
58
|
+
* @param {Object} packageJson Parsed package.json contents.
|
|
59
|
+
* @param {Object} options Build options.
|
|
60
|
+
* @param {string} options.buildDir Path to the CJS build directory.
|
|
61
|
+
* @param {string} options.buildModuleDir Path to the ESM build-module directory.
|
|
62
|
+
* @param {string[]} options.target esbuild target configuration.
|
|
63
|
+
* @param {Object} options.wasmInlinePlugin The WASM inline plugin for esbuild.
|
|
64
|
+
*/
|
|
65
|
+
export async function buildWorkers(
|
|
66
|
+
packageDir,
|
|
67
|
+
packageJson,
|
|
68
|
+
{ buildDir, buildModuleDir, target, wasmInlinePlugin }
|
|
69
|
+
) {
|
|
70
|
+
if ( ! packageJson.wpWorkers ) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const workerBuilds = [];
|
|
75
|
+
const workerEntries =
|
|
76
|
+
typeof packageJson.wpWorkers === 'object' &&
|
|
77
|
+
packageJson.wpWorkers !== null
|
|
78
|
+
? Object.entries( packageJson.wpWorkers )
|
|
79
|
+
: [];
|
|
80
|
+
|
|
81
|
+
for ( const [ outputName, entryPath ] of workerEntries ) {
|
|
82
|
+
const workerEntryPoint = path.join( packageDir, entryPath );
|
|
83
|
+
const workerOutputName = outputName.replace( /^\.\//, '' );
|
|
84
|
+
|
|
85
|
+
// Build ESM worker for build-module (primary for browser use).
|
|
86
|
+
if ( packageJson.module ) {
|
|
87
|
+
workerBuilds.push(
|
|
88
|
+
esbuild.build( {
|
|
89
|
+
entryPoints: [ workerEntryPoint ],
|
|
90
|
+
outfile: path.join(
|
|
91
|
+
buildModuleDir,
|
|
92
|
+
`${ workerOutputName }.mjs`
|
|
93
|
+
),
|
|
94
|
+
bundle: true,
|
|
95
|
+
format: 'esm',
|
|
96
|
+
platform: 'browser',
|
|
97
|
+
target,
|
|
98
|
+
sourcemap: true,
|
|
99
|
+
// Bundle everything - workers need to be self-contained.
|
|
100
|
+
external: [],
|
|
101
|
+
plugins: [ wasmInlinePlugin ],
|
|
102
|
+
define: {
|
|
103
|
+
'process.env.NODE_ENV': JSON.stringify(
|
|
104
|
+
process.env.NODE_ENV || 'production'
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
} )
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Build CJS worker for the `build` directory (Node.js compatibility).
|
|
112
|
+
//
|
|
113
|
+
// Note: We only generate CJS worker bundles when the package exposes a
|
|
114
|
+
// CommonJS entry point via `packageJson.main`. Packages that are ESM-only
|
|
115
|
+
// or browser-focused (for example, packages that have removed their
|
|
116
|
+
// `main` field like `@wordpress/vips`) will not produce CJS worker
|
|
117
|
+
// outputs, and will instead rely solely on the ESM worker built into
|
|
118
|
+
// `build-module`. This conditional is intentional to avoid creating
|
|
119
|
+
// unused or misleading CJS artifacts.
|
|
120
|
+
if ( packageJson.main ) {
|
|
121
|
+
workerBuilds.push(
|
|
122
|
+
esbuild.build( {
|
|
123
|
+
entryPoints: [ workerEntryPoint ],
|
|
124
|
+
outfile: path.join( buildDir, `${ workerOutputName }.cjs` ),
|
|
125
|
+
bundle: true,
|
|
126
|
+
format: 'cjs',
|
|
127
|
+
platform: 'node',
|
|
128
|
+
target,
|
|
129
|
+
sourcemap: true,
|
|
130
|
+
external: [],
|
|
131
|
+
plugins: [ wasmInlinePlugin ],
|
|
132
|
+
define: {
|
|
133
|
+
'process.env.NODE_ENV': JSON.stringify(
|
|
134
|
+
process.env.NODE_ENV || 'production'
|
|
135
|
+
),
|
|
136
|
+
},
|
|
137
|
+
} )
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
await Promise.all( workerBuilds );
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Generate inline worker code exports and re-transpile worker-code.ts.
|
|
147
|
+
*
|
|
148
|
+
* Creates worker-code.ts with bundled content for Blob URL loading,
|
|
149
|
+
* then re-transpiles it to the output directories.
|
|
150
|
+
*
|
|
151
|
+
* @param {string} packageDir Path to the package directory.
|
|
152
|
+
* @param {string} packageName Name of the package.
|
|
153
|
+
* @param {Object} packageJson Parsed package.json contents.
|
|
154
|
+
* @param {Object} options Build options.
|
|
155
|
+
* @param {string} options.srcDir Path to the source directory.
|
|
156
|
+
* @param {string} options.buildDir Path to the CJS build directory.
|
|
157
|
+
* @param {string} options.buildModuleDir Path to the ESM build-module directory.
|
|
158
|
+
* @param {string[]} options.target esbuild target configuration.
|
|
159
|
+
* @param {Array} options.plugins esbuild plugins for transpilation.
|
|
160
|
+
*/
|
|
161
|
+
export async function generateWorkerCode(
|
|
162
|
+
packageDir,
|
|
163
|
+
packageName,
|
|
164
|
+
packageJson,
|
|
165
|
+
{ srcDir, buildDir, buildModuleDir, target, plugins }
|
|
166
|
+
) {
|
|
167
|
+
if ( ! packageJson.wpWorkers ) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const workerEntries =
|
|
172
|
+
typeof packageJson.wpWorkers === 'object' &&
|
|
173
|
+
packageJson.wpWorkers !== null
|
|
174
|
+
? Object.entries( packageJson.wpWorkers )
|
|
175
|
+
: [];
|
|
176
|
+
|
|
177
|
+
// Generate inline worker code exports for each worker.
|
|
178
|
+
// This allows the worker code to be bundled inline and loaded via Blob URL,
|
|
179
|
+
// which works even when import.meta.url is not available (e.g., webpack bundles).
|
|
180
|
+
for ( const [ outputName ] of workerEntries ) {
|
|
181
|
+
const workerOutputName = outputName.replace( /^\.\//, '' );
|
|
182
|
+
const workerOutputPath = path.join(
|
|
183
|
+
buildModuleDir,
|
|
184
|
+
`${ workerOutputName }.mjs`
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const workerContent = await readFile( workerOutputPath, 'utf8' );
|
|
189
|
+
const workerCodeFile = path.join(
|
|
190
|
+
packageDir,
|
|
191
|
+
'src',
|
|
192
|
+
'worker-code.ts'
|
|
193
|
+
);
|
|
194
|
+
const workerCodeContent = `/**
|
|
195
|
+
* Worker code for inline Blob URL creation.
|
|
196
|
+
*
|
|
197
|
+
* This file is auto-generated by the build process.
|
|
198
|
+
* Do not edit manually - run \`npm run build\` to regenerate.
|
|
199
|
+
*
|
|
200
|
+
* @package gutenberg
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
204
|
+
export const workerCode = ${ JSON.stringify( workerContent ) };
|
|
205
|
+
`;
|
|
206
|
+
await writeFile( workerCodeFile, workerCodeContent );
|
|
207
|
+
} catch ( error ) {
|
|
208
|
+
console.warn(
|
|
209
|
+
`Warning: Could not generate worker-code.ts for ${ packageName }:`,
|
|
210
|
+
error.message
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Re-transpile worker-code.ts to output directories.
|
|
216
|
+
// The initial transpilation used placeholder content because worker
|
|
217
|
+
// bundling hadn't completed yet. Now that src/worker-code.ts contains
|
|
218
|
+
// the real bundled worker code, re-transpile it so that
|
|
219
|
+
// build-module/worker-code.mjs (and build/worker-code.cjs if applicable)
|
|
220
|
+
// reflect the actual worker code in a single build run.
|
|
221
|
+
const workerCodeSrcFile = path.join( packageDir, 'src', 'worker-code.ts' );
|
|
222
|
+
const retranspileBuilds = [];
|
|
223
|
+
|
|
224
|
+
if ( packageJson.module ) {
|
|
225
|
+
retranspileBuilds.push(
|
|
226
|
+
esbuild.build( {
|
|
227
|
+
entryPoints: [ workerCodeSrcFile ],
|
|
228
|
+
outdir: buildModuleDir,
|
|
229
|
+
outbase: srcDir,
|
|
230
|
+
outExtension: { '.js': '.mjs' },
|
|
231
|
+
bundle: true,
|
|
232
|
+
platform: 'neutral',
|
|
233
|
+
format: 'esm',
|
|
234
|
+
sourcemap: true,
|
|
235
|
+
target,
|
|
236
|
+
jsx: 'automatic',
|
|
237
|
+
jsxImportSource: 'react',
|
|
238
|
+
loader: { '.js': 'jsx' },
|
|
239
|
+
plugins,
|
|
240
|
+
} )
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if ( packageJson.main ) {
|
|
245
|
+
retranspileBuilds.push(
|
|
246
|
+
esbuild.build( {
|
|
247
|
+
entryPoints: [ workerCodeSrcFile ],
|
|
248
|
+
outdir: buildDir,
|
|
249
|
+
outbase: srcDir,
|
|
250
|
+
outExtension: { '.js': '.cjs' },
|
|
251
|
+
bundle: true,
|
|
252
|
+
platform: 'node',
|
|
253
|
+
format: 'cjs',
|
|
254
|
+
sourcemap: true,
|
|
255
|
+
target,
|
|
256
|
+
jsx: 'automatic',
|
|
257
|
+
jsxImportSource: 'react',
|
|
258
|
+
loader: { '.js': 'jsx' },
|
|
259
|
+
plugins,
|
|
260
|
+
} )
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
await Promise.all( retranspileBuilds );
|
|
265
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/build",
|
|
3
|
-
"version": "0.7.1-next.v.0+
|
|
3
|
+
"version": "0.7.1-next.v.202602091733.0+daa0b19c4",
|
|
4
4
|
"description": "Build tool for WordPress plugins.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"wp-build": "./lib/build.mjs"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@emotion/babel-plugin": "11.
|
|
38
|
+
"@emotion/babel-plugin": "11.13.5",
|
|
39
39
|
"autoprefixer": "10.4.21",
|
|
40
40
|
"browserslist-to-esbuild": "2.1.1",
|
|
41
41
|
"change-case": "4.1.2",
|
|
@@ -77,5 +77,5 @@
|
|
|
77
77
|
"publishConfig": {
|
|
78
78
|
"access": "public"
|
|
79
79
|
},
|
|
80
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "74f59922b25e30904319373dda91bf8e81f3544e"
|
|
81
81
|
}
|