react-lazyload icon indicating copy to clipboard operation
react-lazyload copied to clipboard

Support for search bots

Open oyeanuj opened this issue 8 years ago • 17 comments

Hi @jasonslyvia Thank you for putting out this library. Wondering if it supports showing the components to Google and other search engine bots, and/or if that is something you'd consider adding?

oyeanuj avatar Jul 19 '17 05:07 oyeanuj

Do you mean using LazyLoad in Server Side Rendering situation?

jasonslyvia avatar Jul 20 '17 06:07 jasonslyvia

@jasonslyvia I meant showing the images or the components when being crawled by Google, etc, but that is similar to server-side rendering - how does it work to render the image/component then?

oyeanuj avatar Jul 20 '17 13:07 oyeanuj

In SSR case, LazyLoad will render nothing.

jasonslyvia avatar Jul 20 '17 14:07 jasonslyvia

@jasonslyvia I think the search bot case is then different. In that case, you do want to have everything loaded and discoverable.

People tend use the logic specified here or here.

Thoughts?

oyeanuj avatar Jul 20 '17 14:07 oyeanuj

I would also appreciate logic to return the children of <Lazyload> if it's being server-side rendered, instead of <div class="lazyload-placeholder"></div>

andrepcg avatar Oct 19 '17 13:10 andrepcg

What about pages where you want lazyloading for long lists of components but the page itself is server-side rendered? This wouldn't make sense in that regard, it would completely nullify any benefits of using the library

Redmega avatar Oct 23 '17 16:10 Redmega

Currently in need of the same feature. I wonder if this could easily done with a prop to disable the lazy functionality? So everyone could apply their own rules on when to lazyload or not. It's basically: if (noLazy) { return this.props.children } But it should also not attach all events etc

I started taking the lib apart but go a bit lost. Any one up for the implementation? :)

ptrwllrt avatar Oct 30 '17 10:10 ptrwllrt

@cainvommars If you can apply your logic in runtime, why not just:

render() {
  return (
    noLazy ? <Component /> : <LazyLoad><Component /></LazyLoad>
  );
}

So what you ask is basically just an option to implement aforementioned logic?

jasonslyvia avatar Oct 30 '17 10:10 jasonslyvia

@jasonslyvia All good. This is what I've just build. I can totally work with that! Having a boolean to switch lazy on and off would just clean this up and might help others facing the same issue.

<LazyLoadOrChildren
  config={{once: true, offset: 200}}
  noLazyLoad={isThisAServer()}>
    <MyChildren />
</LazyLoadOrChildren>
import * as React from 'react';
import LazyLoad from 'react-lazyload';

function LazyLoadOrChildren(props: {
  config: {
    once?: boolean,
    height?: number,
    offset?: number | $ReadOnlyArray<number>
  },
  children: React.Node,
  noLazyLoad?: boolean
}) {
  if (props.noLazyLoad) {
    return props.children;
  }
  return <LazyLoad {...props.config}>{props.children}</LazyLoad>;
}

LazyLoadOrChildren.defaultProps = {
  config: {
    once: false,
    height: undefined,
    offset: 0
  },
  noLazyLoad: false
};
export default LazyLoadOrChildren;

Btw: Its a nice lib, I just threw it in and it does the job!

ptrwllrt avatar Oct 30 '17 11:10 ptrwllrt

thanks, that's exactly what I expect this lib to do 😉

jasonslyvia avatar Oct 31 '17 02:10 jasonslyvia

@cainvommars How do you know isThisAServer ?

jf423 avatar Nov 09 '17 03:11 jf423

@jf423 One way to do it would be to use a webpack plugin to inject some type of is_Browser variable. https://webpack.js.org/plugins/banner-plugin/

webpack.config.client.js

    new webpack.BannerPlugin({
      banner: "__isBrowser__ = false;",
      raw: true,
      include: /\.js$/
    })

webpack.config.serverjs

    new webpack.BannerPlugin({
      banner: "__isBrowser__ = true;",
      raw: true,
      include: /\.js$/
    })

TikiCat7 avatar Nov 17 '17 02:11 TikiCat7

@jf423 My use case changed slightly. I'm now always render the first 30 photos in a grid and if the index is greater than 30 they get lazy loaded. So no need for the server side detection. - This works for me only because my users can will always start on the beginning of the photo grid.

ptrwllrt avatar Jan 31 '18 07:01 ptrwllrt

Google is able to execute JS, but won't scroll the page. As soon as a non scrollable UA is detected (for example Opera mobile or google bot) all images are transformed instantly. This means google will not see the transparent image, but will probably index your data-src={src}.

For benchmarking consideration: lazysizes approach

oliviertassinari avatar May 22 '18 13:05 oliviertassinari

const img = <img src="/image.jpg" alt="" />;

return (
  <>
    <LazyLoad height={200}>{img}</LazyLoad>
    <noscript>
      <style>{`.lazyload-placeholder { display: none; }`}</style>
      {img}
    </noscript>
  </>
);

During server-side rendering, the placeholder will be placed along with the image in a noscript tag. Search engines will crawl images in noscript tag, while browsers won't load it (until LazyLoad replace the placeholder)!

Also the image will still be shown to users browsing your server-side rendered site with JS disabled!

If you’re using it a lot, consider putting the style tag once for all elsewhere in your document, but still inside a noscript.

IcanDivideBy0 avatar Nov 14 '18 16:11 IcanDivideBy0

@IcanDivideBy0 this was a better solution then checking server. It ensures our markup remains consistent on both client and server renders. Not sure if there is anything react-lazyload could do other then add this as default functionality. It is a major SEO concern.

jhoffmcd avatar Feb 13 '19 19:02 jhoffmcd

Not sure if this is still relevant to anyone but I would suggest adding enabled prop. For example, in Next.JS we have process.browser which is the boolean flag indicating if current environment is SSR or client-side. Using enabled prop we could easily match react hydration processes without mounting and unmounting components.

abriginets avatar Oct 17 '21 16:10 abriginets