Open youknowriad opened 1 year ago
More generally, given the capabilities of clients and the distributed processing power they have (vs the hosts) what can we do client-side to make this as performant as possible.
So, this should be a default compression for all images, or a setting(attribute) in Image
block to compress existing files or probably pass a flag to media upload, when we're in a placeholder state?
If we go with block level support, it means we should implement this to many more blocks, and also users would have to adjust the quality setting each time, for every block.
@ntsekouras I see it as a setting per image but not really a persistent attribute, you decide to compress the image which would update the image if already uploaded or pick a compression factor before upload.
Developing it as block support is not mandatory IMO
This sounds like a great idea to me, and it would tremendously help image performance to have it tightly integrated into right the UI where the user is uploading the image.
If we want to allow users to tweak the compression level per uploaded image, I would suggest that the value chosen, despite not being persistent on the block, is stored persistently as a user preference (i.e. in WordPress user options) so that the compression level that the user chooses effectively becomes the default/initial state for any subsequent images they upload.
There could be quite a few moving parts to consider here, and I'm not sure what the scope for the first iteration should look like, so consider this a first draft of a potential design to kick-off discussion:
In the future this pattern could theoretically scale-up to entertain multiple files and bulk compression, for example when a Gallery block is selected, or even at the document level:
Details like copy and icons can be refined once we decide on a general direction.
@jameskoster Designs look good. Do you think this belongs to the "Advanced" section for blocks or should it be more prominent, like a button in the block toolbar or a dedicate section outside "Advanced".?
@tyxla @jsnajdr While a bit out of scope of the current issue, this feels like a great opportunity to explore "JS lazy loading". The compressor library could be an esm module that you load through the import map API. (Obviously not something that needs to be done in the initial implementation)
FWIW I built a plugin that does this kinda stuff already, using all sorts of WASM stuff. Planning on open sourcing it soon. It could easily be merged into Gutenberg.
I think there are some more nuances here.
@swissspidy does your plugin handle the above replacement case? I'm curious because you say WASM and I expect some PHP to be there..
If we do it in block level(ex Image block) in an already uploaded image, there would be no good way to seamlessly replace the image in all places it's being used(unless I'm missing something in the REST API). What this means is, we have to delete(?) the current image and upload a compressed one. If we delete the image, other blocks that use that image will break. If we replace that image with a new compressed one and keep the old version, we have the risk of multiple compressed images of the same source.
Don't we have a PUT
support in the media endpoint? (updating the files but keeping the same names, urls, ids)
Don't we have a PUT support in the media endpoint? (updating the files but keeping the same names, urls, ids)
No and in general I think WP REST API only uses POST
for updates(doesn't really matter in our case though). I looked a bit at the core attachment controller now and it doesn't seem to handle such a case internally.
We do have a "put" (update media) endpoint https://developer.wordpress.org/rest-api/reference/media/#update-a-media-item It's not clear from the docs whether it allows updating the file itself or just the other properties, if it's not possible, It would be a good addition IMO.
@ntsekouras Yes there‘s also a lot of PHP of course.
You don‘t want to override or delete the original image to prevent data loss and in case the user wants to revert the changes. So you need to upload a new one, mark it as compressed/optimized, and add a way to connect/link it with the original. My solution does all that. Let me prepare a demo for you all this week.
We don't need to invent anything, there's a number of libraries that provide compression APIs like npmjs.com/package/compressorjs
Also worth looking at https://github.com/kleisauke/wasm-vips (maybe that is what @swissspidy's plugin already leverages?)
It's worth also making sure we say how big the image is, and then we can show the before and after in size and quality.
So I wasn't planning on making this public until it was more published, but feel free to check out my media experiments repository here: https://github.com/swissspidy/media-experiments
The readme contains more information about the things I've built already and what I've planned on adding, like bulk optimization. I should be able to get to that soon though.
In the meantime, feel free to reach out to me on Slack if you have any questions.
Here are some demo videos:
@ntsekouras @swissspidy This is really cool, how do you think we can move forward now? Can we transform this to a Gutenberg PR or something?
Probably best to start by discussing this more in the #core-editor chat, as there is a lot to unpack and many things to be considered. My plugin barely scratches the surface of what can be done and goes way beyond what has been originally proposed in this issue here.
In my experience (I have been working with this kind of stuff for multiple years now), something like compressorjs (which just uses canvas.toBlob()
is not nearly enough to accomodate all requirements and browser inconsistencies (e.g. Safari doesn't support quality
or image/webp
).
I would love if my plugin ends up in Gutenberg eventually, but it's not quite there yet. I suggest checking it out a bit more closely and giving it a try yourself.
@swissspidy your plugin seems to do lots of cool stuff 🚀 . Do you think it would be possible to extract something minimal to include in GB and iterate? For example just the image compression without file type conversion etc..
Do you think this belongs to the "Advanced" section for blocks or should it be more prominent, like a button in the block toolbar or a dedicate section outside "Advanced".?
I suggest the Advanced panel because it's the only one that exists for all blocks that might use this affordance. This makes the placement consistent across.
I'd welcome more thoughts, but if the plan is to have a global default 'quality' setting for all uploaded media, then I don't know that this needs to be more prominent. To me it feels like something you'd generally set-and-forget, and the tool in the Advanced panel caters to the edge cases.
It might be useful to have a filterable threshold value, and alert the user somehow (potentially something like https://github.com/WordPress/gutenberg/issues/41747) if an image breaches it, similar to the color contrast warnings.
Including a preview with size details in the modal (as per @swissspidy's plugin) would be neat. Especially if it can update dynamically as you adjust the quality value.
Users often have to use online services like https://imagecompressor.com or alternatives to optimize their images. It would be great to explore offering a button (or something like that) right in the image block to compress uploaded images.
We don't need to invent anything, there's a number of libraries that provide compression APIs like https://www.npmjs.com/package/compressorjs
Maybe we could suggest an optimal quality and allow the users to tweak the number to avoid compression quality loss.