-
Notifications
You must be signed in to change notification settings - Fork 140
Refine logic to select smaller image file in the frontend based on webp_uploads_prefer_smaller_image_file filter
#302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
felixarntz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjgrainger Mostly looks good, it needs a few small refinements. Most importantly though, I think we should remove the function previously introduced since it's not really helpful or accurate anyway. The new approach here works good just by itself.
8a72560 to
a2719bb
Compare
felixarntz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjgrainger This looks close, two follow-up comments though. One is actually critical, the PR currently doesn't cover the full sized image yet.
Last but not least, can you also add tests for the new logic?
mitogh
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides the comment from @felixarntz this looks good to me @jjgrainger
Thanks.
felixarntz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jjgrainger Production logic now looks good to me, just one nit-pick on the filter and a potential issue with the test.
| // File produces larger webp image, original jpg is smaller. | ||
| $attachment_id = $this->factory->attachment->create_upload_object( TESTS_PLUGIN_DIR . '/tests/testdata/modules/images/leafs.jpg' ); | ||
| $metadata = wp_get_attachment_metadata( $attachment_id ); | ||
| $tag = wp_get_attachment_image( $attachment_id, 'full', false, array( 'class' => "wp-image-{$attachment_id}" ) ); | ||
| $updated_tag = webp_uploads_img_tag_update_mime_type( $tag, 'the_content', $attachment_id ); | ||
|
|
||
| $mime_types = webp_uploads_get_mime_types_by_filesize( array( 'image/jpeg', 'image/webp' ), $attachment_id, 'the_content' ); | ||
| // The full size WebP is smaller. | ||
| $expected_tag = str_replace( $metadata['sources']['image/jpeg']['file'], $metadata['sources']['image/webp']['file'], $tag ); | ||
|
|
||
| $this->assertIsArray( $mime_types ); | ||
| $this->assertNotContains( 'image/invalid', $mime_types ); | ||
| $this->assertSame( array( 'image/jpeg', 'image/webp' ), $mime_types ); | ||
| $this->assertSame( $expected_tag, $updated_tag ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this test in fact doing what the comment above says? It says this test covers the case where JPEG is smaller than WebP, but then for the $expected_tag it replaces the JPEG version with WebP, so that seems not right. If the JPEG version is smaller, the test should expect that the JPEG version is still used even though a WebP version exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @felixarntz
I've updated the comments to make things clearer and reviewed the logic and can confirm it is correct. This image produces a smaller WebP file size of the full image. All sub sizes have a smaller JPG.
I've taken an example of the image code when the webp_uploads_prefer_smaller_image_file filter is set to true here:
<img loading="lazy" width="1080" height="720" src="http://localhost:8888/wp-content/uploads/2022/04/leafs.webp" alt="" class="wp-image-15" srcset="http://localhost:8888/wp-content/uploads/2022/04/leafs.webp 1080w, http://localhost:8888/wp-content/uploads/2022/04/leafs-300x200.jpg 300w, http://localhost:8888/wp-content/uploads/2022/04/leafs-1024x683.jpg 1024w, http://localhost:8888/wp-content/uploads/2022/04/leafs-768x512.jpg 768w" sizes="(max-width: 1080px) 100vw, 1080px">From the srcset you can see all sub sizes use the JPG version as they are smaller than their WebP version.
The replace updates the original image tag, which uses only JPG, to replace the full size with the WebP version in order to match the output of webp_uploads_img_tag_update_mime_type when the webp_uploads_prefer_smaller_image_file is set to true.
I've also created a shorthand version of the metadata array to compare filesizes and this is correct.
Array
(
[file] => 2022/04/leafs.jpg
[full] => Array
(
[image/jpeg] => 336884
[image/webp] => 328322
)
[medium] => Array
(
[image/jpeg] => 19820
[image/webp] => 22332
)
[large] => Array
(
[image/jpeg] => 237115
[image/webp] => 257974
)
[thumbnail] => Array
(
[image/jpeg] => 8082
[image/webp] => 9008
)
[medium_large] => Array
(
[image/jpeg] => 135786
[image/webp] => 153226
)
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks for clarifying. That makes sense, in that case indeed the updated comments look better.
felixarntz
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work @jjgrainger
|
@adamsilverstein @mitogh Can one of you please review this as well so we can get it merged? |
adamsilverstein
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change looks good to me (although I think webp_uploads_prefer_smaller_image_file could start true here), I'll work on adding something similar to the core patch.
| if ( apply_filters( 'webp_uploads_prefer_smaller_image_file', false ) ) { | ||
| $target_mimes = webp_uploads_get_mime_types_by_filesize( $target_mimes, $attachment_id ); | ||
| } | ||
| $prefer_smaller_image_file = apply_filters( 'webp_uploads_prefer_smaller_image_file', false ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
working on adding to core patch so this could be true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamsilverstein Not sure we should add this to the initial core patch as it feels like an extra enhancement. The main patch has a ton of code already and this enhancement could easily be separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll add it as a separate patch
| if ( | ||
| $prefer_smaller_image_file && | ||
| ! empty( $metadata['sources'][ $target_mime ]['filesize'] ) && | ||
| ! empty( $metadata['sources'][ $original_mime ]['filesize'] ) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at this part I realized that there could potentially be several mime types in the sources array (eg. JPEG, WebP, AVIF), we should probably check all of them for the smallest size, rather than just the original and the mapped type.
What do you think @felixarntz ? Fine to address in a follow up so we can get this merged since it covers our primary use case as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamsilverstein That's a good point, I think eventually that would make sense. It would require a bit more complex reworking though indeed, for example right now we only have a single $target_mime, and then there will need to be a list, all of which we would need to go through.
+1 to doing it in a separate issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm taking the "look thru every mime type for the smallest" approach for the (follow up) core patch, basically go thru all sources to find the smallest and use that:
foreach( $metadata['sources'] as $source ) {
if ( empty( $source['filesize'] ) ) {
continue;
}
if ( $source['filesize'] < $target_file['filesize'] ) {
$target_file = $source;
}
}webp_uploads_prefer_smaller_image_file filter
Summary
Fixes #292
Relevant technical choices
webp_uploads_prefer_smaller_image_filefilter is enabled.Checklist
[Focus]orInfrastructurelabel.[Type]label.no milestonelabel.