-
-
Notifications
You must be signed in to change notification settings - Fork 937
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
Cannot lazy load images in Firefox or Chrome #1828
Comments
Thanks @rschristian. Hmm.. I'd think the other framework most similar to our version would be Lit. We do a similar template cloning approach to rendering so. We clone all the elements. and then set the attribute before we attach it to the DOM. Effectively the code ends up being: const _tmpl = document.createElement("template");
_tmpl.innerHTML = `<div><div>Spacer</div><img loading="lazy" height="150" width="150">`;
const _el = _tmpl.content.firstChild.cloneNode(true),
_el2 = _el.firstChild,
_el3 = _el2.nextSibling;
_el2.style.setProperty("height", "200vh");
_el3.setAttribute("src", "/path/to/asset.svg"); |
I can add that Lit isn't subject to the aforementioned FF & Safari issue with its implementation or any problems in Chrome (that I saw; I have been testing 6+ frameworks across 6+ browsers, it's possible I missed something of course). I'm not sure where or in what details you diverge from Lit, but that might be worth looking into first. |
Ok I finally looked at this. My results for your Solid example: MacOS: Windows Basically I only see the issue in Firefox in both OSs. In Chrome changing the order didn't seem to matter either. But Firefox seems to always eagerly load. I think I may have figured out the difference with Lit. They use |
I know the fix but it is slower. I didn't want to make a call here without figuring out of this is spec or a firefox bug. |
@ryansolid, I have the same problem without lazy loading, <img class={style.commentAvatar} src={local.avatar} /> if I just remove <img class={style.commentAvatar} /> |
To be fair this issue is about whether lazy works in the given browser. My testing indicated that only Firefox wasn't lazy loading images. That is something we are looking at fixing. If images themselves are rendering slow that's a different thing and probably has nothing to do with Solid. If Chrome or Safari are locking up with images it comes down to how they are rendering them because all we are doing is setting the src attribute. That could be a reason to use lazy but that is outside this issue (unless lazy isn't working as the spec intends). |
@ryansolid, it can be fixed with |
Sure.. I'm saying that the |
there is no difference, both with loading="lazy" and without it still slowing down rendering |
Until it's clear if it's a Firefox bug or something that should be addressed in Solid, is there a workaround for this? Maybe using the Intersection Observer API manually would be the simplest approach? |
Seems like this issue will be fixed in Svelte 5 maybe some inspiration can be taken from there? |
It looks like they are implementing my suggestion higher in the thread #1828 (comment) I just have been hesitant because it means worse perf for everyone. But it is probably ultimately the right decision. We just haven't had a minor release in Solid for a while. Not sure when I want to get it in. |
…ix firefox has problems with `img`s and `loading="lazy"`. see solidjs/solid#1828
…ix firefox has problems with `img`s and `loading="lazy"`. see solidjs/solid#1828
Final going to be fixed soon in 1.9. Fixed by commit: 2a3a198 |
Seems like the fix unfortunately doesn't handle this case It always defaults to using cloneNode() for these cases. I can reproduce the lazy images being loaded immediately in firefox when doing so. Vs hardcodeing <img
loading={props.isPrioritisedImage_ ? "eager" : "lazy"}
// Other attributes
/> |
Yeah limit of the compiler analysis. So dynamic expressions can't be hoisted. I suppose we could just look for the loading prop in general and assume that you want to do the slower method regardless of true/false. |
I was thinking the same, pretending |
Yeah that would be great! Would appreciate that. |
Would just switching to importNode in these cases be enough? The reason I ask is if we ever switched to always use importNode we wouldn't need the extra logic. |
I think the problematic use case is when A possible issue I could think of, is when both the |
I see. I was expecting it still to only fire when connected. Probably because I believe cloneNode didn't until then. But I guess this is another difference with I'm surprised though that Lit wouldn't have this problem then. I imagine it importNode before apply dynamic expressions. |
Thanks, I understand now what you said. I suspect you are right, but then something is off because the difference between Just for clarification my previous message is confusing the behaviour of an image when inside a |
Consideration: If I understand the specification correctly, when an image lazy loads, depends on so many factors, that we can consider it "unknown" and have practically no realistic expectations about it. Among implementation suggestions for "lazy load scroll margin" are:
https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-load-root-margin That being said, I went into the original report here, run the code and it works as expected (per the considerations above). ex: images are lazy loaded with solid v1.7.8 and even with solid v1.9.x There are a few gotchas about that code:
Ryan is correct and images won't load when used by Unfortunately there's still a bug in Firefox, when a partial is cloned Firefox won't respect Just in case, it doesn't seem to be a problem with the container https://playground.solidjs.com/anonymous/c382f493-516b-4661-b968-ddee3d7e4dc9 I suppose frameworks, such as Lit, don't have this problem because they set the property dynamically and do not template-clone, which make them slow. Svelte switched their mechanism to set the I have entered this bug in mozilla https://bugzilla.mozilla.org/show_bug.cgi?id=1926802 Possible workarounds:
|
Yes, I can reproduce your problem. I understand something new, that should have been evident by the comment on the Svelte code.
I am trying to understand why inlining in your example This falls into wontfix territory in my opinion, because introducing microtasks to fix this will cause race conditions with any "advanced" use of imgs in apps. |
Hmm I don't understand why you need a microtask. All I need is the extra arguments ( By the way, I think the solidJS playground runs an outdated solid-js version. I wanted to make an example: https://playground.solidjs.com/anonymous/cd61a8ba-d91a-439f-b91c-c6c99b2756ac but it didn't work. If you check the code, it's because no extra arguments are passed to While if I run it with my local solid-js setup they are there: |
Here try this, here the image loads as expected, when you scroll down: So this would be the expected output for the given input: It works perfectly for me. Make sure to have devtools open and cache disabled here for reliable re-tests: |
Thanks @danieltroger very useful, so uh, there is indeed a difference between You can toggle It seems to also work with dynamic values https://playground.solidjs.com/anonymous/c7cc0e4a-fdc8-4419-8906-dfcd4263ffbc I have updated the PR to remove adding So I suppose we are good to go and this PR should in theory work. |
I suppose this doesn't work in Svelte because they are doing as I did, clone the whole template https://github.com/sveltejs/svelte/blob/86ef18165f35d132f77b711263f00899f8134554/packages/svelte/src/internal/client/dom/template.js#L51-L62 |
Ah good find!
Niice! |
Describe the bug
(I'm putting this first as I think it's important pretext, sincere apologies if this throws anyone off)
FireFox and Safari have rather interesting behavior regarding setting the
src
property of an image element, in that the browser will attempt to fetch the media after a microtask, regardless of whether or not the element has been (or will be!) inserted into the DOM. This is rather simple to demonstrate:Using the Network pane of a browser's devtools, you'll see the immediate fetch of the image.
FF Bugzilla Report: it's unclear whether this is a bug in FF & Safari or a spec issue, but it's been around for a while now.
Because of this, if one wants to set the image to lazy load, in Safari and FF, one needs to ensure the
loading
prop is set first, else it's effectively not set at all. Preact, React, and Vue mirror vanilla JS behavior, makingloading
an ordered prop in their JSX and SFCs.As we try to decide what to do about this for Preact, I've been testing this behavior through multiple frameworks to see who accounts for this and who doesn't, but Solid's results have been exceptionally odd: lazy loading doesn't seem to work, regardless of property order, in FireFox and Chrome (tested desktop & mobile for both). However, it DOES work correctly on iOS Safari (I don't have a Mac so can't test desktop, sorry).
In the above mentioned frameworks, Chrome had been handling out-of-order properties just fine, meaning one could use
<img src"..." loading="lazy" />
without any issue. I'm not quite sure what about Solid's implementation differs to cause Chrome to now have issues, or why Safari now works as expected, but something seems to be off.This could very well be browser bug / spec issue territory, of course.
Your Example Website or App
https://github.com/rschristian/solid-lazy-img-bug
Steps to Reproduce the Bug or Issue
yarn
yarn dev
(Alternatively,yarn build && yarn preview
, issue can be reproduced in both)solid.svg
, despite being quite far out of the viewportExpected behavior
The image should be lazily loaded, only being requested when near the viewport / after a scroll.
Screenshots or Videos
No response
Platform
Additional context
No response
The text was updated successfully, but these errors were encountered: