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

Prefetch & Prerender #21

Closed
HadrienGardeur opened this issue Dec 6, 2016 · 10 comments
Closed

Prefetch & Prerender #21

HadrienGardeur opened this issue Dec 6, 2016 · 10 comments

Comments

@HadrienGardeur
Copy link

During our last conference call, I mentioned that several browser engines support rel="prerender": http://caniuse.com/#feat=link-rel-prerender

This is fairly widely implemented on the Web too, for instance Google includes rel="prerender" on the first result of a search if it's confident enough about it. In Chrome, this creates a separate process that prerenders the document and replaces the current tab once you follow the link.

This could be a good strategy on Android (Chomeview) and on desktop (Electron with Chromium or Edge), but won't work on iOS where we might instead rely on multiple webviews.

Has anyone tested rel="prerender" either with a prototype or with Readium-1? I'd like to figure out if this is an option for us, or if the audio/video/script issues that have been mentioned before would make this difficult to use.

cc @danielweck @rkwright

@danielweck
Copy link
Member

danielweck commented Dec 6, 2016

link@rel=prerender prefetching is a smart feature in the sense that although the DOM is "ready" (loosely speaking), it is not actually loaded in an active webview / window context, as it has not been navigated to yet.
By contrast, manual / programmatic document prefetching in "background" / invisible frames may trigger premature behaviours such as (potentially) animations, video/audio playback, Media Overlays, etc.

In Readium-1 cloud reader, EPUB HTML / SVG content documents are loaded into iframes via BlobURI (or the IE / Edge fallback using document.write()), due to preprocessing requirements. So link@rel=prerender would not really be applicable, at least not without significant changes.

In Readium-1 Chrome app, iframe@src is directly bound to a filesystem URL, and the absence of network latency pretty much negates the need for link@rel=prerender (there are other performance bottlenecks totally unrelated to "prefetching" / "resource loading").

@HadrienGardeur
Copy link
Author

Thanks @danielweck, in the meantime I've also been exploring a bit online.

Here are a few useful resources:

Here are a few mental notes so far:

  • the specification mentions that the link can be provided in the HTTP Link header (https://www.w3.org/TR/resource-hints/#fetching-the-resource-hint-link) which is extremely easy to implement in the streamer
  • the link can also be dynamically added in a page, which means that this would also work in apps where we use an iframe, we could dynamically add the link whenever we want (for example a page or two before the end of a resource)
  • I can't find anywhere information regarding how long does Chromium keeps the pre-rendered content before it is trashed. On my own laptop (Chrome 54 on OS X) the content remained pre-rendered for 5 minutes before it disappeared from Chrome's task manager. This behavior might be different on another version of Chrome or a different OS.
  • even if it eventually trashed, it has the benefit of prefetching not only the HTML resource that we'd like to display but also the JS/CSS/images/audio/video associated to that resource. In addition to best practices regarding HTTP caching, this means that we should always have the necessary resources in the local cache whenever we need them.

In terms of speed improvements, this should be the most effective:

  • on resources that are quick to read (less than 5mn) such as pages in a Fixed Layout books for instance
  • when we can trigger the pre-rendering at an optimal time, for instance if a search result only returns locators to a single resource, pre-rendering that resource would be a great idea

Overall though, I don't see any good reason not to implement rel="prerender" in the streamer. In Safari and Firefox, we'll be limited to rel="prefetch" which won't be as useful but could still speed things up a little.
For a first naive implementation, we could always prerender/prefetch the next spine item. In FXL publications, we'll also have to support page spreads, in order to load such resources two by two when necessary.
A more advanced implementation could rely on the pagination module to trigger prerendering when the user reaches the last page of a resource.

@danielweck
Copy link
Member

danielweck commented Dec 14, 2016

Additional food for thoughts:
Google AMP
"Browsers have long supported pre-rendering through the <link rel=prerender> tag, but they need to be conservative about this mechanism because prerendering can be expensive."
https://www.ampproject.org/how-it-works/

@jccr
Copy link
Member

jccr commented Dec 14, 2016

Just pushed a branch with a readium-shared-js plugin to experiment with this in Readium 1.

https://github.com/readium/readium-shared-js/tree/feature/preload_experiment

It works best when using the useSimpleLoader flag set to true.
Its logic is simple and it works best with fixed layout EPUBs with a forced one page spread.
I didn't make it support two by two spreads or special cases for reflowable pagination.

My testing workflow uses Chrome, Wireshark, Chrome Dev Tools and the Chrome Task Manager (thanks Hadrien for the tip)

@HadrienGardeur
If you'd like abridged instructions on how to get this running I can provide that for you.

@jccr
Copy link
Member

jccr commented Dec 14, 2016

I should clarify that it does support two by two spreads (a bit hacky, look at the debounce) but it only does a prefetch/prerender for the next spine item (the one half of the next two page spread)

@HadrienGardeur
Copy link
Author

Thanks @jccr

I might actually add support for prefetch and prerender in my prototypes since one of them uses an iframe and the other is purely based on progressive enhancements.
This way we'll be able to test the behaviour for an iframe in Chrome & Edge.

@HadrienGardeur HadrienGardeur changed the title rel="prerender" Prefetch & Prerender Dec 15, 2016
@HadrienGardeur
Copy link
Author

I've added references to prefetch/prerender in both streamer and pagination modules.

@olivierkorner
Copy link

@HadrienGardeur
Copy link
Author

Yeah we also found that article while working on preload/prefetch/prerender in Go and it's quite interesting.

@danielweck
Copy link
Member

The NodeJS implementation supports the same as Go (HTTP header Link prefetch, caching based on ETag hash and If-None-Match)
https://github.com/edrlab/r2-streamer-js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants