This article shares an extension of Turbolinks for accelerating web page access.
Background
Recently, I discovered InstantClick, a small technique for pre-loading web pages, which can effectively improve the speed of website access.
The general principle is that when the user mouses over the link, the web page will be pre-loaded in the cache by Ajax in advance, and when the user clicks, it will be directly rendered with the previous cache.
So I also tweeted about this:
- https://twitter.com/huacnlee/status/1310180334059749378
- https://twitter.com/huacnlee/status/1310209510514909184
Rails built-in Turbolinks actually has a similar cache mechanism. When the user clicks the page back and forth, it will use the cache to pre-render it, but it does not preprocess it when the user's mouse is hovered.
I checked and found that Turbolinks' Issue also discussed this turbolinks/turbolinks#313, and I found an implementation Reference, so I encapsulated it, and made improvements to implement an extension of Turbolinks.
https://github.com/huacnlee/turbolinks-prefetch
At the same time, I have additionally adjusted the visit
action of Turbolinks in the implementation. If there is already a prefetch action, it will be rendered directly without requesting the page again.
As you can see, currently Ruby China has enabled this feature (Hong Kong server). When the prefetch has an effect, the page is basically opened like a local web page.
How Turbolinks Prefetch works
hover --> [prefetch] --<no cache>--> [XHR fetch] -> [Turbolinks cache.put]
|
<exist cache / in fetching>
|
ignore
click --<check cache>-- exist --> [isPrefetch] -> [Turbolinks.visit advance] ---> [render page]
| | |
| | --async-> [fetch background] -> [render if updated]
| |
| <Yes>
| |--- [Turbolinks.visit restore] --> render -> nothing
No cahce
|
---> [Turbolinks.visit]
Installation
$ yarn add turbolinks-prefetch
Usage
import Turbolinks from 'turbolinks';
window.Turbolinks = Turbolinks;
import TurbolinksPrefetch from 'turbolinks-prefetch';
TurbolinksPrefetch.start();
When a Prefetch request is made, an additional HTTP header of Purpose: prefetch
will be sent. If you need to ignore certain actions, you can use it.
For example, actions such as updating the reading status and the number of visits:
class TopicsController < ApplicationController
def show
if request.headers["Purpose"] != "prefetch"
# Do not update visits during prefetch
@topic.increment_hit
end
end
end
Disable Prefetch for some links
By default, Turbolinks Prefetch will turn on the behavior for all links.
Except for the following situations:
- Links to different websites (Host / Origin are different);
- There is a link to open a new window
target="_blank"
; - Links with
data-remote
attribute; - There are links with
data-method
attributes; - Links with
data-prefetch="false"
attribute;
It should be said that you don't need to deal with most of the default situations. The default behaviors like Rails UJS are already handled in Turbolinks Prefetch.
So you can disable prefetch for some links like this:
<a href="https://google.com">Google</>
<a href="/topics/123" target="_blank">Open in new window</a>
<a href="/topics/123" data-method="PUT" data-remote>Put</a>
<a href="/topics/123" data-method="DELETE">Delete</a>
<a href="/topics/123" data-prefetch="false">Disable by directly</a>
GitHub
๐ Don't hesitate, immediately use it in your projects that already use Tubrolinks, basically seamless support.
Top comments (1)
We had a similar solution but will check out your repository. Thanks for sharing the article and code ๐