-
Notifications
You must be signed in to change notification settings - Fork 18
Use single regex for loading/srcset/sizes, and only modify attachment images #20
Conversation
@joemcgill Could you maybe have a look at this? |
} | ||
|
||
// The following filters are only needed while this is a feature plugin. | ||
add_filter( 'wp_get_attachment_image_attributes', '_wp_lazy_loading_add_attribute_to_attachment_image' ); | ||
add_filter( 'get_avatar', '_wp_lazy_loading_add_attribute_to_avatar' ); | ||
|
||
// The following relevant filter from core should be removed when merged. | ||
remove_filter( 'the_content', 'wp_make_content_images_responsive' ); |
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.
wp_make_content_images_responsive
is used in a lot of plugins, some with > 1m installs. Removing or changing how it works is not a good idea.
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.
It wouldn't be changed, it just would no longer be used by core. Also I'm curious how it is being used by plugins?
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.
Mostly to run content through it: https://wpdirectory.net/search/01E0PTA8MSD8ZHCC7V4QDG9EV3 but some may be removing it, which will fail if it is not used in core.
Also deprecating a "popular" function is generally not a good idea. I know, sometimes there's no way around it, but not convinced this case qualifies :) (There are about 200 plugins that use the function. If we rename and deprecate it, they will have to "catch up" or will fill millions of error logs with "deprecated" entries.)
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.
For the purposes of plugin development, the function needs to be replaced.
This discussion can be moved to an issue for wider input from the media team closer to any merge proposal.
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.
@peterwilsoncc How do you mean "the function needs to be replaced", can you clarify? Not sure I understand.
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.
@felixarntz I mean if you'd like to use a single regex while developing this plugin, you'll need to remove the core filter and replace it with a duplicate in this plugin (as the team has done in this PR).
This allows the naming/deprecation discussion to happen outside of this PR.
wp-lazy-loading.php
Outdated
if ( $add_loading && false === strpos( $filtered_image, ' loading=' ) ) { | ||
$filtered_image = wp_image_add_loading( $filtered_image, $image_meta, $attachment_id, $content, $context ); | ||
} |
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.
Doing that here will bypass all images that don't have a wp-image-####
class. This means all images that were not added directly in the post editor, and images that were added in the editor by pasting the URL will be excluded.
As images are not supported in comments and excerpts by default, that will make it pointless to filter there at all. Chances are that even if the users have added images there (perhaps by using a plugin), the images will not have the required class name.
Frankly don't think this limitation makes sense. We are still looking only in user-added content. Excluding some images because they are not "local" or depending on the way they were added doesn't seem good?
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 agree with that sentiment, but there's also no harm in being conservative at the start and only covering attachment images. We can easily make this work also with other images too (pass attachment ID 0), but that doesn't mean we need to right away.
I don't have a strong opinion on this, but 3P images, e.g. tracking pixels, may have different implications. We assume there's no issue, but we don't know for sure. Covering 3P images here could easily become a follow-up (separate PR or even separate core release if needed).
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.
no harm in being conservative
Right, but this is mostly an "artificial" limitation: "You get lazy loading of images but only if they are uploaded to WP and are inserted properly by using the editor. Other images will not be lazy-loaded because...." (we said so?) :)
But yes, I agree this is not a huge issue as the majority of images in post_content will have the attachment ID class (as it has been used for srcset and sizes for a while). Skipping images that don't have it will skip all "images from URLs" perhaps including images from CDNs, which would be pretty disappointing for the feature.
wp-lazy-loading.php
Outdated
*/ | ||
function wp_add_lazy_load_attributes( $content, $context = null ) { | ||
function wp_filter_content_attachment_images( $content, $context = null ) { |
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.
If we are going to deprecate wp_make_content_images_responsive()
(this is a replacement function for it), thinking that limiting it to only images that have a specific class name would be wrong.
Perhaps something like https://github.com/WordPress/wp-lazy-loading/pull/9/files#diff-229cc76004131ce077176ab5955e8707R236 but limited only to img
tags would be better? Otherwise the new function still has a limitation that doesn't seem to make sense.
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.
We could easily change the regex to also cover images without that class if we decide to. In that case, we would only try to get the attachment if the class is present, and otherwise assume 0.
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.
Yeah, looked a bit at how to do this and didn't like any of the alternatives. As it is currently, we will do _prime_post_caches()
(expensive) even when not adding srcset and sizes. Can probably make that and wp_get_attachment_metadata()
conditional on $add_srcset_sizes
. But then cannot pass $image_meta
to wp_image_add_loading()
and passing $attachment_id
will be "undesirable" as plugins would probably use it to get the meta anyway.
Still thinking moving wp_image_add_loading()
to the first loop makes more sense. Alternatively we should only run this on the_content
as it is currently for srcset and sizes.
wp-lazy-loading.php
Outdated
* @param string $context Additional context to pass to the filters. | ||
* @return string Converted 'img' element with 'loading' attribute added. | ||
*/ | ||
function wp_image_add_loading( $image, $image_meta, $attachment_id, $content, $context ) { |
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 the patch as a whole, not sure it makes sense for this to be a separate function. Also the name doesn't sound that well, perhaps. If it is to stay, perhaps something like
wp_image_add_loading_attribute( $image_tag, ... )
to make it clear it is only for <img>
HTML tags, etc.
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 think it makes sense for this to be separate, just like the existing function for srcset and sizes is separate. Regarding the name, I followed the convention set in that existing function too.
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.
it makes sense for this to be separate, just like the existing function for srcset and sizes
Yeah, you're right.
Regarding the name, I followed the convention set in that existing function too.
Wouldn't call it a convention, it's rather a self-documenting thing: describe what the function does in 4-5 words or less. The add srcset (and) sizes
sounds pretty specific, add loading
is quite general though. Perhaps add loading attr
? At least it suggests that there's an HTML attribute involved.
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.
Well, srcset
and sizes
are attributes just like loading
and the term "attribute" is excluded there. But I don't have a strong opinion on this.
It would be nice to reuse the existing regex that filters post_content to add srcset and sizes attributes to image tags. However looking at how to do it brings several problems:
Why the limitation? As far as I understand "tracking pixels" work fine when they have loading=lazy. Any evidence they do not? Any other evidence/edge cases where all "non-local" images should be excluded?
Right. The attachment_ID is required when adding My understanding is that all images in user added content should be loaded lazily. Excluding some for seemingly no good reasons doesn't look good? If there are specific edge cases that are currently not handled well in the browsers lets find them. |
Another thing that this change doesn't take into account is the eventual need to add |
Some (small) optimizations and name tweaks. Return early if there's nothing to do, etc.
Can you point out what kind of abstraction you envision here? Should we maybe turn it into
I think we can modify the regex to become Your latest changes look good to me. What do you think about merging this and then following up with another PR on expanding |
Looking again, there have been quite a few developments nicely outlined in https://make.wordpress.org/core/2020/02/25/lazy-loading-update/. In that terms seems the "only modify attachment images" part should go. By the time this gets merged, all major browsers will support the new HTML living standard. It doesn't seem good to artificially limit this functionality to only images where we know the attachment ID.
Yep, changing functions and vars names to make them non-image-specific as in f02acc2 would be enough for now (imho). Still a bit concerned about having to remove |
Added this PR as an enhanced/alternate patch (didn't want to overwrite this PR). Can be merged/backported here if needed. |
Closing this in favor of #23 |
This PR addresses #2, and various other related concerns:
wp_filter_content_attachment_images()
which essentially is a copy of core'swp_make_content_images_responsive()
, modulo the addition of an optional$context
parameter and the secondforeach
loop (for each attachment image). This is the key change in this PR, which addresses Optimize performance of regex for addingloading
attribute #2.wp_image_add_srcset_and_sizes()
remains inwp_filter_content_attachment_images()
. It is now only called if the$context
(the current filter) isthe_content
, because that is the only filter this logic currently applies to, and it shouldn't be modified here because it's unrelated (even though maybe worth considering in the future). The check for an existingsrcset
attribute was moved here because it shouldn't determine theimg
tags to generally iterate through.wp_filter_content_attachment_images()
is hooked into the regular content filters like the previouswp_add_lazy_load_attributes()
was.wp_make_content_images_responsive()
is unhooked fromthe_content
. Once this is merged to core, the hook should be removed, and the function could be deprecated.loading
attributes to images that shouldn't be modified, such as tracking pixels. Since WordPress core's existing logic already gets the attachment IDs and even image meta anyway, there's no performance concern here.wp_image_add_loading()
now takes care of modifying a single image tag. Its name, signature and behavior is inspired by the existingwp_image_add_srcset_and_sizes()
. It now also receives the$image_meta
and$attachment_id
already fetched by core anyway. There are now also passed to thewp_set_image_loading
filter.do_blocks()
(which runs on 9) so should cover enough, while at the same time ensuring there's no unexpected breakage withsrcset
/sizes
. Related: Fix priority #12