Turbolinks extend prefetch to speed up your website 
Tags: ruby, rails, turbolinks, javascript
Published: 2020-10-19 11:30:24

---
title: Turbolinks extend prefetch to speed up your website 
published: true
date: 2020-10-19 17:26:46 UTC
tags: ruby, rails, turbolinks, javascript
canonical_url: https://ruby-china.org/topics/40471
---

This article shares an extension of Turbolinks for accelerating web page access.

## Background

Recently, I discovered [InstantClick](http://instantclick.io), 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/1310180334059749378)
- [https://twitter.com/huacnlee/status/1310209510514909184](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](https://github.com/turbolinks/turbolinks/issues/313), and I found an implementation [Reference](https:/ /gist.github.com/hopsoft/ab500a3b584e2878c83137cb539abb32), so I encapsulated it, and made improvements to implement an extension of Turbolinks.

[https://github.com/huacnlee/turbolinks-prefetch](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.

[https://github.com/huacnlee/turbolinks-prefetch](https://github.com/huacnlee/turbolinks-prefetch)