Skip to content
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

SSR, image not rendered from server #86

Open
Gorbus opened this issue Jan 16, 2021 · 6 comments
Open

SSR, image not rendered from server #86

Gorbus opened this issue Jan 16, 2021 · 6 comments
Labels
needs investigation ssr Related to Server Side Rendering

Comments

@Gorbus
Copy link

Gorbus commented Jan 16, 2021

Bug description
The lazy loading is working perfectly on client side but none of my image are rendered from the server on the original loading SSR. Is there a special config to change in order for the image to be rendered as SSR? Stack is Meteor/React/Apllo/Styled Component

<StyledLazyLoadImage
  alt={`product image ${name}`}
  scrollPosition={scrollPosition}
  src={imgUrl200 ? imgUrl200 : imgUrl}
/>
const StyledLazyLoadImage = styled(LazyLoadImage)`
  margin: 0.5rem;
  max-width: 18rem;
  max-height: 22rem;
`;

Also tried without the scrollPosition but result is the same.

Expected behavior
Was expecting the image to be rendered on server side.

Screenshots
image

Technical details:

  • Package version: 1.5.1
  • Server Side Rendering? Yes
  • Device: Desktop
  • Operating System: MacOs
  • Browser: Chrome
@foubei
Copy link

foubei commented Mar 2, 2021

Have you solved it?

@jigar775
Copy link

jigar775 commented Mar 5, 2021

Facing same issue.

@Aljullu Aljullu added needs investigation ssr Related to Server Side Rendering labels Aug 13, 2021
@petr-glaser-deltatre
Copy link

I can confirm, this issue is still here. :/

@petr-glaser-deltatre
Copy link

petr-glaser-deltatre commented Jan 13, 2022

Found the issue. The library is SSR friendly in a way it does not crash. So the flow on SSR with disabled JS is this:

  • Start render on server
  • PlaceholderWithoutTracking is rendered and !supportsObserver is true
  • updateVisibility is called, but typeof window === 'undefined' is true, so false is returned
  • SSR renders placeholder, default placeholder is <span>

Solution is to use placeholder={<img src={src} loading="lazy" />} which will keep the image rendered even on SSR with JS disabled.

@ItsRyanWu
Copy link

ItsRyanWu commented Jul 6, 2022

Found the issue. The library is SSR friendly in a way it does not crash. So the flow on SSR with disabled JS is this:

  • Start render on server
  • PlaceholderWithoutTracking is rendered and !supportsObserver is true
  • updateVisibility is called, but typeof window === 'undefined' is true, so false is returned
  • SSR renders placeholder, default placeholder is <span>

Solution is to use placeholder={<img src={src} loading="lazy" />} which will keep the image rendered even on SSR with JS disabled.

This way seems to be reasonable and workable and in the meantime we can still use placeholderSrc in parallel as the placeholderSrc will be used as a CSS background image property of the <span/> wrapper and the placeholder elements we explicitly set is a separate <img/> tag inside the wrapper.
Btw a quick reminder that don't forget to set srcSet to the <img/> tag for the placeholder property if the original image is supposed to be assigned with it, otherwise your browser will waste network bandwidth to load unnecessary image files according to the src at first and then load the next correct resolution version according to the srcSet on the real <img/> tag after the website is mounted.

@ItsRyanWu
Copy link

ItsRyanWu commented Jul 6, 2022

Found the issue. The library is SSR friendly in a way it does not crash. So the flow on SSR with disabled JS is this:

  • Start render on server
  • PlaceholderWithoutTracking is rendered and !supportsObserver is true
  • updateVisibility is called, but typeof window === 'undefined' is true, so false is returned
  • SSR renders placeholder, default placeholder is <span>

Solution is to use placeholder={<img src={src} loading="lazy" />} which will keep the image rendered even on SSR with JS disabled.

I think an even better solution is we could wrap the <img/> inside the placeholder property with <noscript> tag, so it's will become only readable to the search engine and won't be executed by browsers in normal cases. I personally think it's a good way to improve performance when it's being parsed by browsers, as the placeholder is not really needed if you already set placeholderSrc property.
So the final answer from me would be like this:

placeholder={
  <span>
    <noscript>
      {/* eslint-disable-next-line @next/next/no-img-element */}
      <img src={src} srcSet={srcSet} sizes={sizes} alt="placeholder" />
    </noscript>
  </span>
}

To be noticed that a <span/> or other non <noscript/> tags is required here to be a root node to prevent <LazyLoadImage/> from being failed to mount the real image element.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation ssr Related to Server Side Rendering
Projects
None yet
Development

No branches or pull requests

6 participants