-
Notifications
You must be signed in to change notification settings - Fork 10.3k
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
chore(gatsby-image): lazy-load refactor #14158
chore(gatsby-image): lazy-load refactor #14158
Conversation
This seems it was intended for discussion when implementing. It doesn't have value in the source code. There is no special handling needed, no concern to make a maintainer aware of, nor is a default set like stated, only when the prop exists.
There is no need to pass in a prop to indicate native lazy-load support, that is inferred by the `loading` prop. There is no need to have conditional checks and a spread operator, just assign the prop value to `loading`. If the prop doesn't exist(loading==false), it's ignored by React.
Extracted feature detection to vars to avoid the interleaving logic flipping booleans, especially with `isVisible`. `hasNoScript` => `addNoScript` `IOSupported` => `hasIOSupport`/`useIOSupport` `nativeLazyLoadSupported` => `hasNativeLazyLoadSupport` This clarifies intentions, reducing complexity and thus increasing readability of the entire flow. `isVisible` is false during SSR(avoiding being rendered into markup prior to hydration) unless `critical` is present). `isVisible` is true upon hydration when `critical` is present, or in a browser that has native lazy-load support or when IO support is not available. If false upon hydration, the markup lacks the main `<picture>` element until `isVisible` is true, such as when triggered by an IO event.
`render()` should not be calling `convertProps()` twice to handle overwriting / mapping `loading` based on `critical`. That is what `convertProps()` is specifically for. Moved logic there and moved the deprecation notice into a reusable function. Perhaps the `resolutions` and `sizes` legacy props should also utilize it? Removed the comment, based on new context it should be clear. Also avoided overwriting `loading` if `critical==false`, `auto` is a possible value for `loading`. The || fallback shouldn't ever be hit AFAIK?
No point running this logic for each class instance?
As the method is only for lazy-loading with IO support, there is no need to bail early, `useIOSupport` just needs to be false if native lazy-load support exists.
Additionally, remove the original `isVisible` declaration (now a duplicate), and a small refactor in `convertProps()` Note the formatting changes that Prettier requested seem to have the opposite effect of being more readable/maintainable.
This PR is failing tests due to this, not sure how this didn't raise a failure in it's own PR?
Dealing with the failing tests atm. The recent PR for a customizable That's the only error failing jest from master, I've got a commit for it in this PR to push addressing it.
3 jest snapshot errors due to UPDATE: Seems warnings can pass the unit tests, I only noticed it due to snapshot mismatch error. Updated snapshot, it should include the loading attribute regardless since the prop is given a default of Do you want the test verifying the default |
`loading="lazy"` should be in the snapshot, which believes it's in a browser(so not SSR), but no IO or lazy-load support, thus `isVisible` is true as expected. The original feature PR avoided the attribute if the feature was not supported by the browser(but includes it in noscript), no negative impact from including it.
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.
This is awesome! This looks really good!
test to include eager or auto via the loading prop instead with an expect() rule to verify?
I would do this also check if critical is mapping on eager.
Move the environment check into `logDeprecationNotice()` which is what it was most likely intended for. `critical` is already typed as a boolean and treated as one elsewhere, no need to do a type check, it's not polymorphic like `bgColor`. Treatment only needs to assign `eager` as the `loading` attribute is already set as `lazy` by default.
Turns out the props passed in are immutable, hence why they were copied with `{ ...props }` in the first place :)
Verify default is `lazy`, test `critical` prop sets `eager`.
As requested: gatsbyjs#14158 (comment) `useIOSupport`,`addNoScript`,`seenBefore` all become properties of the `Image` class. `hasNativeLazyLoadSupport` isn't used anymore, other than in the constructor. Reduced the state calls in `handleImageLoaded()` to 1. Changed the order of `shouldReveal` to align with `shouldFadeIn`.
There doesn't appear to be purpose in delaying until `handleImageLoaded()`? `seenBefore` would not change, someone might change `fadeIn` to true inbetween but I can't think of why we'd want to override that? Added `isBrowser` guard mainly to communicate more clearly that it has no effect in SSR(image needs to load before it can be true, regardless of duplicates during SSR). Since the initial vars set up top aren't used, I placed them in the state directly.
c923232
to
cd6204b
Compare
This should be good to merge, I still need to address the two concerns pointed out at the top after my edit, but I'm a bit busy for the rest of the month. |
Looks good! thanks for updating. Doing a test run and it will be ready to merge. |
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.
Looks good! Thanks for cleaning up & thanks for your patience!
Description
LightRefactor around the recent changes from adding native lazy-loading support. For some reason most of my review on the PR was ignored(even after requesting feedback after a couple weeks of inactivity).Best reviewed via individual commits for clarity and each commits message detailing what was done.
Prettier in some cases made some changes less pretty. Related issue on Prettier repo.
Questions / Concerns
~~Do you really want to only map critical to loading in dev, not production? Or did you only want to raise the deprecation notice in dev? ~~
Is there any reason to use a ternary? Shouldn't it just check if critical is true?EDIT: Above concern has been addressed. Same as the suggestion above, but no strict equality check since other conditions on the prop just check for truthiness.
critical
is now advised against being used to have usage replaced withloading
attribute instead via this message and docs. Howevercritical
is still relevant in theImage
constructor andcomponentDidMount()
, this advice may cause issues to be opened due to confusion as the prop is not 1:1 replacement atm.imgCached
will be false in situations that IO isn't used for lazy-load, thusshouldFadeIn
won't be disabled, which afaik means we'll probably run into #12254 again?