-
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
Opt-out of lazy-load: Add 'critical' flag to Img component #7083
Conversation
@@ -69,24 +69,6 @@ const listenToIntersections = (el, cb) => { | |||
listeners.push([el, cb]) | |||
} | |||
|
|||
let isWebpSupportedCache = 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.
Using picture tag makes this obsolete
packages/gatsby-image/src/index.js
Outdated
@@ -141,7 +123,7 @@ class Image extends React.Component { | |||
|
|||
// If this image has already been loaded before then we can assume it's | |||
// already in the browser cache so it's cheap to just show directly. | |||
const seenBefore = inImageCache(props) | |||
const seenBefore = !props.critical && inImageCache(props) |
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 may be a bit controversial - if a critical image is used in multiple places on a page, but has different fadeIn values - one of the critical image may not appear when the component is mounted.
packages/gatsby-image/src/index.js
Outdated
@@ -168,10 +154,16 @@ class Image extends React.Component { | |||
this.handleRef = this.handleRef.bind(this) | |||
} | |||
|
|||
componentDidMount() { | |||
if (this.props.critical) { | |||
this.setState({imgLoaded: 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.
onLoad can not be relied on to change the state for images that where loaded from the DOM
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.
What did you change here? If you push individual commits, that's helpful to people reviewing your code.
BTW, did you see #4297 (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.
Here I fixed up the lint error about spaces around braces.
Deploy preview for using-postcss-sass failed. Built with commit fd48bb3 https://app.netlify.com/sites/using-postcss-sass/deploys/5b68dfb4e39e7c630cd35077 |
handleRef(ref) { | ||
if (this.state.IOSupported && ref) { | ||
listenToIntersections(ref, () => { | ||
this.setState({ isVisible: true, imgLoaded: false }) | ||
this.setState({ isVisible: 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.
Not sure why this was set to false here. Reseting the state to false causes issues with critical images, and I could not find where non-critical images required this state change.
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.
hmmm yeah, don't remember either 😅
packages/gatsby-image/src/index.js
Outdated
alt={alt} | ||
title={title} | ||
src={image.src} | ||
srcSet={image.srcSet} |
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 there really a need to include srcSet, and sizes in the fallback? It appears that browsers that support these on img
also implement picture
- so it is added weight, without a purpose.
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.
👍 sounds right to me.
Deploy preview for using-drupal ready! Built with commit fd48bb3 |
Deploy preview for gatsbygram ready! Built with commit fd48bb3 |
Deploy preview for gatsbyjs failed. Built with commit fd48bb3 https://app.netlify.com/sites/gatsbyjs/deploys/5b68dfb3e39e7c630cd3506b |
packages/gatsby-image/src/index.js
Outdated
}), | ||
}} | ||
/> | ||
{!this.props.critical && ( |
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.
May need to walk this back - if fadeIn
is true - and there is no scripting enabled - the loaded image will not appear
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 still true, or was this fixed? I can't see which commits this came from 🙃
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 has been revised like so:
gatsby/packages/gatsby-image/src/index.js
Line 323 in 198535f
{this.state.hasNoScript && ( |
packages/gatsby-image/src/index.js
Outdated
srcSet={image.srcSet} | ||
sizes={image.sizes} | ||
style={imageStyle} | ||
onLoad={() => { |
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.
should onLoad
event handler be used in <source>
as well? or maybe it would work using it in <picture>
?
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.
Img is a required tag in picture. It would seem to me that it would be redundant?
I have adjusted my local branch to support fadeIn for All that should be left is verifying that onload on Gatsby-Image is called if the image is downloaded before the script bundle is loaded. |
Deploy preview for using-contentful failed. Built with commit 2c873b3 https://app.netlify.com/sites/using-contentful/deploys/5b7c68c5e39e7c6abe678f98 |
Implementation notes: * use Picture tag to allow browser to select best matching file format (webp detection) * if fadeIn is true (default) - then the loaded image still will not appear until after the component is mounted * the inImageCache should ignore 'critical' assets or images that have different fadeIn behaviors will not trigger an appropriate change in state (won't show loaded image) see example: ``` <Img fixed={images.file1.childImageSharp.fixed} /> <Img fixed={images.file1.childImageSharp.fixed} /> <Img fixed={images.file2.childImageSharp.fixed} critical fadeIn={false}/> <Img fixed={images.file2.childImageSharp.fixed} critical/> ```
Mimic behavior of lazy-images bypassing fadeIn when `seenBefore==true` Trigger load-complete script on componentDidMount if the image is loaded prior to the JS load complete Modify imagePlaceholder transitionDelay to reduce flicker present on critical images at tail end of fade (observed on Chrome 67.0) `noscript` `img` transitioned to use `picture` tag so that only one resource is downloaded in the event that JS is disabled when `critical==true + fadeIn==false`
Added webp src to mock data Updated Snapshot with <picture>
@KyleAMathews not sure about the ci failures. Looks like most prs are failing? Otherwise I think this PR is feature complete. |
this.state = { | ||
isVisible, | ||
imgLoaded, | ||
IOSupported, | ||
fadeIn, | ||
hasNoScript, | ||
seenBefore, |
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.
stored to evaluate on mount to emulate the lazy behavior
} | ||
|
||
this.imageRef = React.createRef() |
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.
need a reference to the HTMLImageElement to evaluate the completed state - to detect if DOM finished loading image before the JS started
@@ -194,13 +214,14 @@ class Image extends React.Component { | |||
|
|||
const imagePlaceholderStyle = { | |||
opacity: this.state.imgLoaded ? 0 : 1, | |||
transitionDelay: `0.25s`, | |||
transitionDelay: this.state.imgLoaded ? `0.5s` : `0.25s`, |
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.
when transitioning a critical
image to opaque:1 - Chrome 67/68 flashes/flickers - not certain if there's a reason to synchronize the placeholder while fading in the real image.
...imgStyle, | ||
...placeholderStyle, | ||
} | ||
|
||
const imageStyle = { | ||
opacity: this.state.imgLoaded || this.props.fadeIn === false ? 1 : 0, | ||
opacity: this.state.imgLoaded || this.state.fadeIn === false ? 1 : 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.
Fade in now copied from props at construction time. Can be mutated if a critical image has been seen before.
resolves #4297 |
@tbrannam I plan to check this out this afternoon, so stay tuned :) First thing I noticed is we're using the |
Yes - picture was built to fallback to img (img is a required field) I
don't think a polyfill would be necessary. IE11 doesn't appear to support
srcset at all either - so I think the behavior I think is unchanged with
this PR.
It's probably worth mentioning in the docs.
…On Fri, Sep 7, 2018 at 1:31 PM Dustin Schau ***@***.***> wrote:
@tbrannam <https://github.com/tbrannam> I plan to check this out this
afternoon, so stay tuned :)
First thing I noticed is we're using the picture element now--which is
cool--but that's not supported in IE 11 (per usual...). I *think* this
will gracefully fallback to the image element (i.e. the picture tag will
just be ignored) but it could be worth mentioning this in the gatsby-image
documentation and then linking to appropriate polyfills. What do you think?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7083 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAEz3RduRUfaJRQoWg5ieu3QoHVKPCcRks5uYq1igaJpZM4VxM3Y>
.
|
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 this looks great. We can/should document the usage of picture
in gatsby-image/README.md, so that people are at least aware of the change.
I validated the following:
- No regressions to existing functionality with
examples/image-processing
project critical
attribute set to true andfadeIn
of false seem to work like I'd expect
@pieh want to chime in here, or are we good to go on merging this?
Update transition style for no fade from `<empty>` to `none`
Added text mentioning the use of `<picture>`
packages/gatsby-image/README.md
Outdated
@@ -277,3 +277,6 @@ prop. e.g. `<Img fluid={fluid} />` | |||
- Images marked as `critical` will start loading immediately as the DOM is | |||
parsed, but unless `fadeIn` is set to `false`, the transition from placeholder | |||
to final image will not occur until after the component is mounted. | |||
- Gatsby-Image now is backed by newer `<picture>` tag. This newer standard allows for |
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 for this!
Holy buckets, @tbrannam — we just merged your PR to Gatsby! 💪💜 Gatsby is built by awesome people like you. Let us say “thanks” in two ways:
If there’s anything we can do to help, please don’t hesitate to reach out to us: tweet at @gatsbyjs and we’ll come a-runnin’. Thanks again! |
In #7083 the css `transition` was moved [from Img](https://github.com/gatsbyjs/gatsby/blob/bcf3af57f3b6438424b712ce1785a6a423b937da/packages/gatsby-image/src/index.js#L117) to [imageStyle](https://github.com/gatsbyjs/gatsby/blob/5ffb1307c17bef802026d5992e1ad000ff654f11/packages/gatsby-image/src/index.js#L224), leaving [imagePlaceholderStyle with a transitionDelay](https://github.com/gatsbyjs/gatsby/blob/5ffb1307c17bef802026d5992e1ad000ff654f11/packages/gatsby-image/src/index.js#L217), but without an actual transition. Although I don't follow everything that changed with that commit, I think that wasn't on purpose. @tbrannam can you confirm?
In gatsbyjs#7083 the css `transition` was moved [from Img](https://github.com/gatsbyjs/gatsby/blob/bcf3af57f3b6438424b712ce1785a6a423b937da/packages/gatsby-image/src/index.js#L117) to [imageStyle](https://github.com/gatsbyjs/gatsby/blob/5ffb1307c17bef802026d5992e1ad000ff654f11/packages/gatsby-image/src/index.js#L224), leaving [imagePlaceholderStyle with a transitionDelay](https://github.com/gatsbyjs/gatsby/blob/5ffb1307c17bef802026d5992e1ad000ff654f11/packages/gatsby-image/src/index.js#L217), but without an actual transition. Although I don't follow everything that changed with that commit, I think that wasn't on purpose. @tbrannam can you confirm?
Address #4297
critical
attribute to opt-out of lazy-loading behavior