Gatsby: Gatsby is not deferring offscreen images, as advertised

Created on 13 Jan 2020  Β·  23Comments  Β·  Source: gatsbyjs/gatsby

Description

One of the stated benefits of using gatsby-image is meant to be automatic lazy loading of images. However, despite using gatsby-image in all the images on our homescreen (both above and below the fold), Google Chrome's Audit tool is revealing that in fact none of these images are being lazy loaded and are all instead loading, as soon as the user hits the page.

Steps to reproduce

We are using gatsby-image like so:

<GatsbyImage
          {...gatsbyImage}
          imgStyle={imgStyle}
          style={style}
          loading="lazy"
/>

where we are querying the image like so:

ollyImage: file(relativePath: { eq: "marketing/olly.png" }) {
      childImageSharp {
        fixed(width: 310) {
          ...GatsbyImageSharpFixed
        }
      }
    }

And passing the resulting props in through ...gatsbyImage.

Expected result

Gatsby-image should not load these images when the user initially hits the page.

Actual result

All images using gatsby-image are being fetched on page load, instead of only when they are in view.

Environment

  System:
    OS: macOS 10.14.4
    CPU: (4) x64 Intel(R) Core(TM) i5-7360U CPU @ 2.30GHz
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 12.4.0 - /usr/local/bin/node
    Yarn: 1.16.0 - /usr/local/bin/yarn
    npm: 6.9.0 - /usr/local/bin/npm
  Languages:
    Python: 2.7.10 - /usr/bin/python
  Browsers:
    Chrome: 79.0.3945.117
    Firefox: 68.0.2
    Safari: 12.1
  npmPackages:
    gatsby: ^2.18.15 => 2.18.15 
    gatsby-image: ^2.2.8 => 2.2.8 
    gatsby-paginate: ^1.1.1 => 1.1.1 
    gatsby-plugin-create-client-paths: ^2.1.3 => 2.1.3 
    gatsby-plugin-google-tagmanager: ^2.1.12 => 2.1.12 
    gatsby-plugin-offline: 2.2.9 => 2.2.9 
    gatsby-plugin-portal: ^1.0.7 => 1.0.7 
    gatsby-plugin-react-helmet: ^3.1.15 => 3.1.15 
    gatsby-plugin-react-svg: ^2.1.2 => 2.1.2 
    gatsby-plugin-s3: ^0.3.2 => 0.3.2 
    gatsby-plugin-sass: ^2.1.4 => 2.1.4 
    gatsby-plugin-sentry: ^1.0.1 => 1.0.1 
    gatsby-plugin-sharp: ^2.3.13 => 2.3.13 
    gatsby-plugin-styled-components: ^3.1.2 => 3.1.2 
    gatsby-plugin-typescript: ^2.1.2 => 2.1.2 
    gatsby-source-filesystem: ^2.1.9 => 2.1.9 
    gatsby-transformer-sharp: ^2.3.12 => 2.3.12 
imagemedia upstream

Most helpful comment

I'll be checking this issue out and see why lighthouse audits fail. I'll keep y'all posted!

All 23 comments

I have noticed this once when I ran lighthouse audits. But then one day that issue just disappeared and I was unable to reproduce it.

@andyhmltn can you possibly give a more descriptive example of the code snippet. I'm specifically curious with what the ...gatsbyImage variable is.

I've had the same issue too but only on Chrome. Firefox and Safari seem to be working properly though.

Hi!

Sorry to hear you're running into an issue. To help us best begin debugging the underlying cause, it is incredibly helpful if you're able to create a minimal reproduction. This is a simplified example of the issue that makes it clear and obvious what the issue is and how we can begin to debug it.

If you're up for it, we'd very much appreciate if you could provide a minimal reproduction and we'll be able to take another look.

Thanks for using Gatsby! πŸ’œ

This might be chrome being more aggressive on their native lazy loading, there is not much we can do unless we revert it. I'll see if I can ask someone from the chrome team to help us understand it.

A link to your site might help me explain what's going on

Thanks for the responses! I'm going to create a test repository to try and recreate this problem, when I get some free time.

@lannonbr
Fair point. That component is just one we made for convinience using gatsby-image that allows us to swap it out for static images, for storybook and the like. The gatsbyImage prop just takes what's returned from a GraphQL query:

GQL Query:
query NotFoundPageQuery {
    bannerImage: file(relativePath: { eq: "404.png" }) {
      childImageSharp {
        fluid(
          maxWidth: 430
          traceSVG: { background: "#F7F8FA", color: "#91A1FF" }
        ) {
          ...GatsbyImageSharpFluid_tracedSVG
        }
      }
    }
  }
Component:
 <Image
      gatsbyImage={bannerImage.childImageSharp}
   />

Hiya!

This issue has gone quiet. Spooky quiet. πŸ‘»

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

I'm having this same issue with my new Gatsby+Sanity (gatsby-source-sanity) site. Safari and Firefox lazy load fine but Chrome does not appear to be, therefore dinging me on my lighthouse score. https://newmantractor.netlify.com

https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fnewmantractor.netlify.com%2F

https://github.com/bzmillerboy/newmantractor.com/blob/master/web/src/components/home.js#L54

I also noticed this. Just started a new site over the last few days with a fresh copy of Gatsby and I'm seeing this in Chrome. I'm thinking that Chrome has changed the methodology for what images they load and there's maybe a bigger "catchment" area for image. The landing page I was working on wasn't particularly long but if I add a load more content to it to increase the viewport, it seems like lazyloading does start to be working for the images much lower down the page.

@bzmillerboy I actually do see lazy loading working on the images further down the page on your site.

For reference:

gatsby: ^2.19.5 => 2.19.16
gatsby-image: ^2.2.16 => 2.2.40
gatsby-plugin-sharp: ^2.4.0 => 2.4.5
gatsby-source-filesystem: ^2.1.9 => 2.1.48
gatsby-transformer-sharp: ^2.2.6 => 2.3.14

Same here, although I am using Gatsby default image with default lazy loading set, Google perf audit says that its not lazy-loaded/deferred properly.

I was digging more into it and could reproduce. The reason why this happens is because chrome's built-in lazy loading have much higher viewport distance thresholds than what gatsby-image is doing when native lazy loading is not enabled.

The threshold in chrome will depend on your connection type - you can check actual values in https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/frame/settings.json5?l=971-1003&rcl=e8f3cf0bbe085fee0d1b468e84395aad3ebb2cad

Per https://web.dev/native-lazy-loading/

General take away - on fastest connection threshold is at least 3000 pixels - and it can increase up to 8000 pixels (for comparison gatsby-image has hardcoded 200px when native lazy loading is not available).

Now i'm not sure if we should allow some way to disable support for native lazy loading or not, but at least there is explanation why this happens

So if lighthouse / audit says that off screen images are not deferred properly - that's on google chrome for their implementation :S (or maybe on lighthouse on being to eager with pointing out issues)

Is there a solution to this? @wardpeet did the Google team get back to you?
If you still need a website to use as a reference point I am in the process of re-building a marketing site and my arguments for using Gatsby was around performance increase and native lazy-loading and deferred images. Will this not be the case in future?

Sorry for taking a while to come back with a reproduction (we hadn't launched.) You can see this in play on our homepage: juggle.jobs

We have noticed the same issue, which you can clearly see by inspecting the network tab for images at the following URL with the window resized narrow enough to ensure lower images aren't loaded straight away: https://co-operate.coop.co.uk/choose-area/. All images are loaded straight away in Chrome, but are lazy-loaded in Firefox.

Incidentally, we're not seeing the issue on this other page: https://co-operate.coop.co.uk/team-notes/week-notes-13-march-2020/ -- @pieh, your comment is on point but doesn't seem to explain that :-/

Something to do with the intersection observer, possibly? The images in the first example are all inside a flex layout, whereas the ones in the second are not. I'll report back if I find anything else.

I'm seeing pagespeed result impact when using native lazy load.
By disabling the native lazy load we got improvement of page speed from 80 β†’ 89.

I would think having the option to opt out native lazy load is a good idea.

The issue is reproducible I can see the same thing in my blog:

https://bhavikji.com/ All the images are getting loaded on the first impression itself.

@LekoArts - Hey, any chance you could remove the 'needs reproduction' label please? I posted a link to our live example (juggle.jobs) two weeks ago, and a few others have also posted reproductions

I'm seeing that same thing on my organization's blog, https://afsp.org/blog. Would it be possible to provide an opt-out option?

I'm also seeing the same problem (Chrome)

I'll be checking this issue out and see why lighthouse audits fail. I'll keep y'all posted!

I also got in quite a tiz when i saw a score of 30 for performance on Lighthouse. After spending all that time learning gatsby.
Felt much better when i ran it through pageSpeedInsights

https://developers.google.com/speed/pagespeed/insights/

Same site gets a score of 95. Phew.

Anyone know why this is?

@SandyWyper. My take is that image fetching is render blocking which affects time to interactive (TTI) as the browser gets "busy fetching" bellow the fold images. Lighthouse' performance score weights are super sensitive to TTI (which is going to change on lighthouse v6) and become less important to the overall score. πŸ€·β€β™‚οΈ

@wardpeet look forward to hearing about your findings. keep us posted πŸ‘

Was this page helpful?
0 / 5 - 0 ratings

Related issues

magicly picture magicly  Β·  3Comments

KyleAMathews picture KyleAMathews  Β·  3Comments

andykais picture andykais  Β·  3Comments

signalwerk picture signalwerk  Β·  3Comments

dustinhorton picture dustinhorton  Β·  3Comments