webp-in-css icon indicating copy to clipboard operation
webp-in-css copied to clipboard

Not compatible with SSR

Open theKashey opened this issue 6 years ago • 10 comments

Well, this library is not SSR compatible, and there are only two reasons why not:

  • README tells to add it to the head or bundle, while it has to be inlined just after body tag
  • it uses onLoad/onError handlers which are async

Let's make it work right!

Long story short - here is working sandbox - https://codesandbox.io/s/crazy-ganguly-hmhe8

  • it inlines base64 img before the body to tell the browser about it. The img is invisible.
  • it "checks" img synchronously after creating, and it does work! (only with a real img tag, preload does not help).
  • so it sets class to the body here and now, and the following HTML would use webp
  • as long as dataURI inlined in the same document - it does not affect gzip size.

Tested

In Chrome(webp ✅), FireFox(webp ✅), and Safari(no webp, as expected)

Outcome

This library becomes SSR friendly!

Happy to open PR with a more compact version of the sandboxed example, however, the main changes are expected at the README level

theKashey avatar Nov 03 '19 04:11 theKashey

Updated version, more compact, simple and sound:

<img
      id="webp-checker"
      style="display:none"  
      src="data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA=="
    />
<script>
document.body.classList.add(
  document.getElementById("webp-checker").height === 1
     ? "webp"
     : "no-webp"
  );
</script>

theKashey avatar Nov 03 '19 04:11 theKashey

Tell me more about your SSR? How do you use library in SSR? What behaviour you expect for SSR?

Don't forget to test in IE.

ai avatar Nov 03 '19 12:11 ai

  • given an image, which shall not be an img tag as long it does not have any contentual sense
  • given a css
&--XXX {
    background-image: url("./assets/XXX-Medium.png");

    @media (min-resolution: 144dpi), (min-resolution: 1.5dppx) {
      background-image: url("./assets/XXX-Large.png");
    }
  }
  • page content is SSR-ed, so should be loaded correctly even without JS (one of the tests - disable JS at all, and applicating should work, more or less)
  • as a result css should be changed to
&--XXX {
    background-image: url("./assets/XXX-Medium.png");

+    :global(.webp) & {
+      background-image: url("./assets/XXX-Medium.webp");
+    }

    @media (min-resolution: 144dpi), (min-resolution: 1.5dppx) {
      background-image: url("./assets/XXX-Large.png");

+      :global(.webp) & {
+        background-image: url("./assets/XXX-Large.webp");
+      }
    }
  }
  • and make webp-in-css work synchronously, not to download all the images twice. In short - this is the main expectation from the library
  • and the initial version was working well only for CRS SPAs.

theKashey avatar Nov 03 '19 21:11 theKashey

make webp-in-css work synchronously

Yeap, this is a good point. But how SSR is related to this? I am worry of missing something important here.

ai avatar Nov 03 '19 21:11 ai

Well, not SSR itself, but preexisting HTML in a root cause. For SPAs, which would render their content on the client-side current behavior is ok - once they would be ready - plugin also would be ready. But for any static content coming from the server - the plugin should also do the job before a browser renders that content. So SSR is not changing the moment "when" plugin should work - always before content render, but adding one more time constraint.

theKashey avatar Nov 03 '19 21:11 theKashey

Got it. You mean for static websites it is great to have synchronous detection.

Let’s test this method in IE and we are ready for PR.

ai avatar Nov 03 '19 21:11 ai

Screen Shot 2019-11-04 at 8 19 25 am

  • In ie it "does not work", as expected
  • in Chrome always works, even if the network cache is disabled
  • in FireFox does not work if dev tools are open, and network cache is disabled.
  • In Safari it "does not work", as expected
  • I am a bit concerned about Chome+Android+Low power mode, where it might automatically "lazy" images, but dont have any device to test.
  • probably due to ^that^ onload/onerror "safety net" should be used.

theKashey avatar Nov 03 '19 22:11 theKashey

In ie it "does not work", as expected

In Safari it "does not work", as expected

What is the probem?

ai avatar Nov 03 '19 22:11 ai

They don't support webp? So that's not a problem at all.

theKashey avatar Nov 03 '19 22:11 theKashey

Got it. Wait for PR.

But let’s keep old JS-only file for compatibility.

ai avatar Nov 03 '19 22:11 ai