This article shares an extension of Turbolinks for accelerating web page access.
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:
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.
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.
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]
$ yarn add turbolinks-prefetch
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
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
- Links with
- There are links with
- Links with
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>
🎊 Don't hesitate, immediately use it in your projects that already use Tubrolinks, basically seamless support.