Skip to content

Client Side Media Testing branch #75189

Closed
adamsilverstein wants to merge 343 commits intotrunkfrom
feature/client-side-media-dev-testing
Closed

Client Side Media Testing branch #75189
adamsilverstein wants to merge 343 commits intotrunkfrom
feature/client-side-media-dev-testing

Conversation

@adamsilverstein
Copy link
Member

@adamsilverstein adamsilverstein commented Feb 3, 2026

Testing branch

Do not review or merge: testing only.

Note: client side media currently does not work in playground (see WordPress/wordpress-playground#2954),

Includes logging.

Includes

The following PRs have been merged into this test branch:

Testing

For extensive testing instructions, see #74566

adamsilverstein and others added 30 commits January 30, 2026 15:22
Pass the big image size threshold (default 2560) from the REST API
through the settings chain to the upload-media store. This enables
client-side scaling of large images before upload, matching WordPress
core's behavior.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
When an image exceeds the big image size threshold (default 2560px),
scale it down before upload with a '-scaled' suffix. This matches
WordPress core's behavior in wp_create_image_subsizes().

- Add isThresholdResize flag to ResizeCrop operation args
- Update vipsResizeImage to support '-scaled' suffix
- Update resizeCropItem to pass through threshold flag
- prepareItem now adds ResizeCrop operation for threshold scaling

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add tests to verify that:
- Images larger than the threshold (default 2560) are scaled down
- The -scaled suffix is added to scaled images
- Images smaller than the threshold are not modified

Tests skip when cross-origin isolation is not enabled, as the vips
library requires SharedArrayBuffer.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Use sourceFile instead of file when generating thumbnails to match
WordPress core behavior. This ensures thumbnails are created from the
original high-resolution image rather than the scaled version.

Also adds E2E test assertions to verify original_image metadata is
preserved and thumbnails are generated with expected dimensions.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This adds client-side EXIF orientation handling that mirrors WordPress
core's server-side rotation behavior:

- Add exif_orientation field to REST API response for images
- Disable server-side EXIF rotation when generate_sub_sizes=false so
  client can handle rotation using the returned orientation value
- Add rotateImage function to vips package supporting all 8 EXIF
  orientation values (rotations and flips)
- Add vipsRotateImage wrapper in upload-media store utils
- Add Rotate operation type and rotateItem action handler
- Update generateThumbnails to sideload rotated version for images
  that need rotation but weren't scaled (matching -rotated suffix)
- Fix Jest config to resolve @wordpress/vips/worker module for tests
- Add tests for vipsRotateImage function

The implementation ensures:
- Images scaled via bigImageSizeThreshold are auto-rotated by vips
- Small images needing rotation get a -rotated version sideloaded
- Thumbnails are auto-rotated by vips during generation

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add type assertion for exif_orientation parameter
- Export vipsRotateImage from utils for external use
- Add ./worker export mapping to vips package
- Mark @wordpress/vips and wasm-vips as always external in build to handle WASM imports

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Change imports from @wordpress/vips/worker to @wordpress/vips
  (the /worker subpath is not available in trunk and both export the same module)
- Add missing vips reference to upload-media tsconfig.json
- Remove unnecessary ./worker export from vips package.json
- Remove jest config mapping for vips/worker
- Remove E2E test that relies on vips library functionality
- Fix prettier formatting in wordpress-externals-plugin.mjs

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The vips package uses WASM modules which Vite cannot handle directly
during the Storybook build. Exclude it from optimization and mark it
as external for SSR to prevent build failures.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add a Vite plugin that stubs the @wordpress/vips module with no-op
functions for Storybook. This prevents the WASM module loading error
during build since Vite cannot handle WASM imports directly without
additional plugins.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add enforce: 'pre' to run the plugin before others, and extend
stubbing to cover wasm-vips package and all .wasm file imports.
This ensures all WASM-related imports are stubbed before Vite
tries to process them.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
adamsilverstein and others added 9 commits February 6, 2026 11:53
Sets the default maxConcurrentImageProcessing value in the
upload-media store's DEFAULT_STATE so the concurrency limit
is active out of the box.
These selectors mirror the existing upload concurrency
selectors and will be used to enforce limits on concurrent
VIPS/WASM image processing operations.
Without this gate, all images start VIPS/WASM processing
simultaneously when uploaded in bulk, consuming 50-100MB+
each and crashing the browser. Now at most 2 run at once.
Without this, items gated by the concurrency limit would
never be retried. Mirrors existing pattern where finished
uploads trigger pending upload items.
After bulk image processing, the WASM worker can hold
hundreds of MB. Terminating it when the queue is empty
frees that memory. The worker is lazily re-created on
next use.
Covers getActiveImageProcessingCount and
getPendingImageProcessing, verifying they correctly
identify ResizeCrop and Rotate operations.
The Storybook vips stub and Jest test mock were not updated
when terminateVipsWorker was introduced, causing CI failures.
When client-side media processing is enabled, the spinner
and dimmed overlay now persist while sub-sized images are
being generated and uploaded, preventing users from closing
the window or publishing with missing image sizes.
@github-actions github-actions bot added the [Package] Block library /packages/block-library label Feb 6, 2026
Move dependencies after engines to satisfy the
prefer-property-order lint rule.
…-lock-trunk' into feature/client-side-media-dev-testing
…oad-save-lock-trunk' into feature/client-side-media-dev-testing"

This reverts commit 606cf68, reversing
changes made to 8656035.
…-lock-trunk' into feature/client-side-media-dev-testing
The vips package generates a 10MB+ worker-code.ts file
during builds that crashes ESLint's text-table formatter.
The file is already in .gitignore.
The @wordpress/vips/worker module contains ~10MB of inlined
WASM code. Loading it eagerly at module parse time adds
unnecessary overhead when no image processing occurs. This
defers the import to the first actual vips function call
and caches the module for subsequent use.
The block-library package depends on @wordpress/upload-media
but the tsconfig reference was missing, causing the
lint:tsconfig CI check to fail.
The upload-media IIFE bundle was 3.81MB because vips (with
inlined WASM) was bundled inline. Adding wpScriptModuleExports
to the vips package lets the build system externalize it,
producing a separate on-demand script module. Upload-media
drops to ~19KB; vips loads only when image processing runs.
…d-images

# Conflicts:
#	packages/editor/src/components/provider/use-block-editor-settings.js
The hardcoded createWasmVipsCommonJsPlugin in wp-build contained
package-specific knowledge about wasm-vips. This moves the resolve
config into the vips package's wpWorkers declaration and replaces
the plugin with a generic createModuleRedirectPlugin that reads
from the new config. Also documents the wpWorkers config format.
The inline type had crop typed as just boolean, but
WordPress's add_image_size() also accepts a positional
array like ['left', 'top']. Reuse the existing
ImageSizeCrop interface which already has the correct type.
…media-dev-testing

# Conflicts:
#	packages/editor/src/components/provider/index.js
#	packages/editor/src/components/provider/use-block-editor-settings.js
@adamsilverstein
Copy link
Member Author

The feature is now testable in trunk. Closing.

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

Labels

[Feature] Client Side Media Media processing in the browser with WASM No Core Sync Required Indicates that any changes do not need to be synced to WordPress Core [Package] Block editor /packages/block-editor [Package] Block library /packages/block-library [Package] Core data /packages/core-data [Package] Editor /packages/editor [Status] In Progress Tracking issues with work in progress [Type] Feature New feature to highlight in changelogs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Maintain Client Side Media feature branch for testing

4 participants

Comments