
Show HN: An Almost Ideal React Image Component - stereobooster
https://github.com/stereobooster/react-ideal-image/blob/master/introduction.md
======
matthberg
It would be cool to optionally integrate SVG placeholders, a-la:
[https://medium.com/@jmperezperez/using-svg-as-
placeholders-m...](https://medium.com/@jmperezperez/using-svg-as-placeholders-
more-image-loading-techniques-bed1b810ab2c)

(previously discussed:
[https://news.ycombinator.com/item?id=15696596](https://news.ycombinator.com/item?id=15696596))

~~~
stereobooster
It supports SVG placeholders. SVGs need to be converted to data URIs, like
`data:image/svg+xml,%3csvg xmlns='...`, and it works the same as LQIP. You can
use
[https://github.com/stereobooster/sqip.macro](https://github.com/stereobooster/sqip.macro)
to generate those

------
samhunta
This is a great start. Some lightweight features that would make this even
more ideal (for me) would be:

\- retina/3x support \- support for styled components extend feature (if can
be made a lightweight implementation) \- maybe default max width of 100% on
mobile? \- optional ability to overlay an empty full size block so the image
cant easily be right clicked and saved

~~~
stereobooster
It supports retina/3x. Provide big enough image and it will use it. It takes
into account `devicePixelRatio`

> maybe default max width of 100% on mobile?

It is.

> optional ability to overlay an empty full size block so the image cant
> easily be right clicked and saved

Not sure what you mean, but as soon as image loaded it turns into good old
image, so you can do right click

~~~
anonfunction
>> optional ability to overlay an empty full size block so the image cant
easily be right clicked and saved

> Not sure what you mean, but as soon as image loaded it turns into good old
> image, so you can do right click

I believe he wants the opposite of that, putting a div over the image so it
cannot be right clicked and saved.

------
jbob2000
This is amazing, but I feel like there is something fundamentally lacking from
<img> if you have to do all this bullshit _just to get an image to display_.

Why can’t the image and DOM spec be upgraded to include lazy loading and touch
to download? I can’t think of a use case where you wouldn’t want this.

~~~
TheRealPomax
That's kind of the browser's responsibility, really. The image element already
covers what is required to instruct the user agent that there a) is an image
resource and b) what its location is. It's then up to the browser to do the
right thing with that data. It's nice that people are finding ways to preempt
that in case the browser they're in is dumb as dirt, but it's really not the
role of the spec to tell user agents how to deal with loads of images. If I'm
browsing my gigabit intranet image repositories on any of our workstations, I
don't want my user agent to be "intelligent" and just load everything, because
it can. If I'm on LTE mobile, I want my browser to be a little smarter about
swapping in/out image content. If I'm on 3G, I don't want the browser to load
any images at all unless I tell it to. But those are my wants, those are not
things the spec should "ordain" user agents must (in the spec definition of
must) do.

React components like these are nice, but the real question is why doesn't
your _browser_ already do this. Not "why doesn't the spec say what needs to
happen", but why haven't Microsoft, Google, Mozilla, Opera, etc. implemented
network-and-content-traversal-appropriate image handling? (one answer might be
"because apparently users don't actually ask for it enough", but I honestly
don't know).

~~~
zaroth
Because there’s no way to standardize the behavior across user agents to the
extent necessary that developers could actually rely on it producing a
consistent experience across a large user-base.

~~~
TheRealPomax
Conversely, there is also no way to standardize which solution to use to the
extent necessary that developers could actually rely on it producing a
consistent experience across a large user-base.

You don't need standard behaviour, you just need _good_ behaviour. And if
every browser does that differently, but it's appropriate to the network speed
and processing capabilities, then as a dev the issue of "making sure images
load appropriately" becomes as irrelevant as "making sure your webfont
actually loads" has become in the modern browser landscape.

------
TheAceOfHearts
I've previously experimented with image loading components for fun. Similarly,
I implemented the material design image loading spec for the web a few years
ago.

This may come off a bit negative, but I disagree that it provides a better UX.
I don't know if I've grown jaded or cynical, or if we just have drastically
different preferences. I think embedding a thumbnail with a link to the full-
sized image is better; it's certainly simpler. In general, I don't think the
tradeoffs are worthwhile.

Some thoughts:

* There is no mention of module size. That can have a big effect on your initial pageload. Of course, this depends a lot on the context in which you are using said module. It might still be sensible for certain kinds of galleries, perhaps less so for an application for which images are of secondary concern.

* The discussion on performance is too focused on mobile and having very few images on the screen at the same time. What about desktop? What if you plan on having more than two images on-screen at the same time? Doing a comparison with traditional img tags on a grid-view gallery with 100 images would be much more interesting.

* I think it would be genuinely interesting to see what the real-world experience would be if you took a popular website and dropped this in. I do not believe that it would often be an improvement. The two sites that come to mind are 4chan and Reddit.

~~~
stereobooster
Module size is ~7Kb. A detailed comparison is here
[https://github.com/stereobooster/react-ideal-
image/blob/mast...](https://github.com/stereobooster/react-ideal-
image/blob/master/other/idealimage-vs-img.md)

> The discussion on performance is too focused on mobile

Because mobile users have a slower internet connection and worse CPUs.

What kind of performance are you talking about? If load performance, then this
component uses well-established techniques (not invented by me), like lazy-
loading (known since jQuery times), srcset (web standard), LQIP (used by
Facebook, Medium), width, height (required for all blocks in AMP).

If you are talking about JS performance like frame rate or paint or "junk" on
the scroll - I didn't measure it but didn't say it was the first target
either.

------
ggregoire
Wow this is great.

Right now I'm using a homemade <ImgWithPlaceholder src={src} /> that displays
a generic gray PNG on 404 or src null.

I'll definitely try your lib as a replacement. I'm excited about the out-of-
the-box lazy loading and the LQIP (never heard before.)

------
sunsetMurk
Well this is very cool. On my MVP projects I'm happy to get any of those
things to happen.

I would LOVE an angular service that did this that I can re-use. If only I had
the time to fork this and make it work... May need to explore this over the
weekend.

Thanks for putting this together!

------
stanislavb
Seems very interesting. I'll give it a shot and try integrating it @
SaaSHub.com. Thanks for sharing and implementing it.

------
dstroot
Why do I love stuff like this sooo much? (I really do)

Consider the yak shaved. :)

~~~
stereobooster
Oh yes. More than one

------
chrismorgan
You know what’s an almost ideal image component? <img>. Sure, browsers could
be a little cleverer about prioritising image loading, and I wish everyone
would prefer to slim their images down somewhat, but compared with all other
attempts I have encountered (with no exceptions), <img> is almost ideal.

I unconditionally _hate_ all scroll-based lazy loading of images. Any other
forms of lazy loading of images such as you outline in this post I will also
hate, p≥0.96. And attempts to be clever like detecting high latency and
working otherwise in such situations normally mess up what I want to happen.

I’ve written about these things before and I’ll doubtless write about it
again;
[https://news.ycombinator.com/item?id=16518010](https://news.ycombinator.com/item?id=16518010)
is the last time I wrote about it on HN and some discussion arose. (The
previous time was on the SVG image placeholders article linked elsewhere in
these comments.)

~~~
chacham15
Most of this comment is just you being dismissive about an idea without any
real reason presented for being dismissive. The only useful bit here is
actually in your linked comment which most people will probably not see and
that is that lazy loaded images tend to fail a lot on poor internet
connections. I would argue that even in that case, lazy loading images arent
necessarily bad depending on the situation: imagine a site like imgur, where
you will likely browse to another page without ever loading all of the images.
In that case, the browser would still have loaded the image if it were an img
tag and this way you get to the next page faster. Sometimes the browser will
cancel the img download, but its not reliable. If the js were coded to handle
errors on loading the image, that would probably be a better situation
overall.

~~~
chrismorgan
It’s much worse than just the potential for failure, as I indicate in other
places I’ve written about it. If I ever see evidence that scroll-based lazy
loading has occurred, _it has failed in its mission_ : it didn’t load the
image in time. And in practice, this happens a lot of the time, especially in
higher latency situations. You can’t sufficiently-well predict what the user
is going to do and so only load it just in time. It doesn’t work.

I am inspired by your grumbling to write a blog post entitled “Scroll-based
lazy loading of images is _always_ bad”. I won’t publish it for a while so I
can treat the subject methodically (and I’m busy for the rest of today), but
it will come.

Thanks for the imgur comparison; the wording I’ve used does fall down there;
in my mind I had distinguished scroll-based lazy loading and scroll-based lazy
loading of _images_. When talking about scroll-based lazy loading of images, I
meant where you have content that _contains_ images, rather than situations
where the images _are_ the content. (That is, I’m talking about lazy loading
just the <img>, not lazy loading content in general.) There are definitely
applications for which loading everything up-front is impossible (e.g. imgur
infinite scrolling on mobile) or impractical (e.g. showing all the 10,000
messages in a mailbox in an email client that deliberately eschews pagination,
like FastMail); in such situations, lazy loading is necessary and while it
will often be annoying and imperfect there is and can be no better solution.

Where images are embedded in the content, however, I think that my position is
still reasonable; there is an alternative: just load eagerly rather than
lazily. Now articles and blog posts are the primary application I have in
mind, and I can’t think of any other applications where my position would not
hold—given the caveats of interpretation specified in the previous
paragraph—but I’m willing to hear other suggestions.

------
jabn76
I hate lazy loading. - bit offtopic: Are there any good browser extensions
that stop this behaviour?

~~~
stereobooster
Can you explain why?

~~~
ec109685
You have to wait for react to load and initialize on the client before an
image can load.

~~~
connorelsea
images and everything else bc client-side rendering... not sure how this is an
argument for not lazy-loading images though

~~~
anothergoogler
As an end user it feels slow. If I hold my space bar on a website created in
1995, I can scan the entire page contents.

~~~
stereobooster
What you are talking about is more like graceful degradation. If server side
rendering is used you will be able to see content ASAP, but not able to
scroll, because interaction is blocked by JS. But if you will visit page with
JS disabled you will get what you want, because component generates img in
noscript tag and you will be able press space to scan the page

~~~
anothergoogler
Actually pages that use a component like the one in this submission typically
show a blurry "beer goggle" version of the image, waiting for JS to replace
them with a hi-res version. So with no JS you get a page of beer goggle images
(BBC does this for instance).

~~~
stereobooster
But not this component. This component will load images without JS. Test it
yourself [https://stereobooster.github.io/react-ideal-image-
experiment...](https://stereobooster.github.io/react-ideal-image-experiments/)

------
faitswulff
It would be helpful if the repo stated why this was ideal - and as opposed to
what?

~~~
JasonSage
If you click through it actually tells you all the things it provides which
you wouldn't get with a vanilla img tag.

~~~
faitswulff
Ah, didn't realize it wasn't a top-level readme. For the lazy:

> I need React component to asynchronously load images, which will adapt based
> on network, which will allow a user to control, which image to load.

------
meesterdude
I know this'll get downvoted, but this looks like an awful lot of work for...
displaying images in a browser. As other HNers have said, it feels like the
browser should be doing this work rather than having to create round about,
convoluted JS solutions to deliver simple functionality.

Plus, I don't get what's exciting about this. But I'm also not a react guy -
and this does nothing to make me consider picking it up. Which, is counter to
all the cool JS libraries i've pulled into projects over the years, which
naturally induced a desire to learn more JS.

I guess if you're hyper focused on react or frontend js in general, this sort
of stuff might be more appealing and relevant. but dear god I've got way more
important/interesting things to do than spend a day getting images to render
in the browser. Nor does this do anything to lower the barriers of entry for
people with an idea and a desire to build something. Sometimes I wonder if
that's a design intent.

anyway, sorry for the rant. Great job identifying/solving problems, but i
don't get the appeal.

~~~
unclebucknasty
I don't get why a comment like this is downvoted. The commenter is simply
saying that he doesn't understand the hype. This site is getting nearly
unbearable with the groupthink, particularly around specific tech or
frameworks.

/meta

On this particular issue, I will go further than my parent and say this does
not represent a significant step forward in the scheme of things. The problem
being solved here is largely akin to a problem I had to solve 15+ years ago
with Vanilla JS. It is positively nuts that we are celebrating a "fix" for it
all of these years later, and that we are investing so much time on what
should be routine by now.

Anyone who is genuinely excited about this should sincerely be asking
themselves if it's a good thing that a lengthy post/fairly involved component
for sanely displaying images in a browser is the state-of-the-art for Webdev
in 2018.

Yes, I get it: browsers don't do x or y. So, yeah, let's add more libs, more
frameworks, more shims, more specs...more, more, more. It's almost self-parody
by now. Look at the average Webapp of any semi-significant complexity. It is
such a hodge-podge of code, languages, technologies, build steps, etc. that
it's a wonder any of it works.

I think it's time we all took a step back and ask, "what are we doing? Is this
the right model? Is there a better way?"

~~~
enobrev
( I didn't downvote the parent )

> The problem being solved here is largely akin to a problem I had to solve
> 15+ years ago with Vanilla JS.

Of course these problems (multiple!) can be fixed with vanilla js. They all
have been, separately, each in their own libraries and stackoverflow posts and
custom vanilla code on every project in the past couple decades. The linked
page does an excellent job of pointing out the libraries and SO posts it's
utilizing to resolve these issues.

The purpose of the linked component is to pull in all these vanilla js fixes
and tweaks at once, in a way they'll all work together. A drop-in component to
utilize years worth of tweaks and fixes, so you don't have to worry about this
crap anymore. Doesn't that kind of cover your complaint? We shouldn't have to
deal with it anymore. Drop this in, and worry about something more
interesting.

> I think it's time we all took a step back and ask, "what are we doing? Is
> this the right model? Is there a better way?"

I picked React long before most of my colleagues did, and I continue to feel
it's one of the most useful libraries in quite some time for browser-based
javascript development. Mostly because it allows for something like this very
library - drop-in and move on to something better.

I was also a huge fan of jquery - not because I couldn't do what jquery was
doing for me, but because I was tired of doing it repeatedly for different
browsers and for each and every project. Same goes with prototype.js when it
first came out, though I hated how it modified the underlying objects.

If I'm understanding your post correctly, I feel like these are all attempts
to resolve the issues you're speaking toward. To allow us to stop dealing with
cross-browser, cross-device, 2-cans and a string connection issues that,
ideally, our browsers should be handling for us.

At least we don't have to rely on flash to replace missing browser
functionality anymore (I say that as someone who absolutely loved
ActionScript3).

~~~
unclebucknasty
> _The purpose of the linked component is to pull in all these vanilla js
> fixes and tweaks at once, in a way they 'll all work together._

Is it acceptable that this is the state of the art? That, 15-20+ years on, we
are fixing the same problem and, further, that we are doing so by rolling a
bunch of cruft into yet another framework? Is this really what we are shooting
for?

> _A drop-in component to..._

> _Drop this in, and worry about something more interesting_

Drop it in after learning and adopting a fairly heavyweight framework that
forces you to code to a completely different paradigm. Do we really think this
is an acceptable solution for simply displaying images on a Web page? I think
that's really telling WRT how far off the map we've wandered.

> _Doesn 't that kind of cover your complaint?_

> _I feel like these are all attempts to resolve the issues you 're speaking
> toward._

I think React and others are really symptoms of the problem, which is an
impedance mismatch between the static document model that underpins the
platform on which we are now trying to build fully dynamic applications.

Rather than continuing to paper over browser deficiencies, there needs to be
some collaboration between the webdev and browser communities to define more
consistent behavior for common scenarios and a standard component/event based
model of the type that has proven suitable for GUI-based applications. The Web
standards of HTML, DOM, CSS, etc. should not be first-order constructs in this
new model. That is, devs should not work in them directly and, to the extent
that these standards are useful due to their currently-broad browser support,
they should be generated by tooling. We should be laying out our UIs on
canvases in our IDEs with flexible grid layouts, and hanging event handlers
off of various events a la Swing.

We need to break the current DOM/old Web model that tells us React and others
are good simply because they make the impedance mismatch slightly less painful
and paper over some browser deficiencies.

~~~
enobrev
(I didn't downvote your posts either)

I went on a weird tangent with my reply to this comment and just I'm just
going to replace it with this. I generally agree with what you're saying as a
means forward, but I also think React is a fantastic tool in the meantime.

What we have is, in fact, the state of the art for better or worse. We will
get beyond this, but it clearly takes time.

