本文分享 Turbolinks 的扩展,用于加速网页访问。
最近发现了 InstantClick 这种对网页预加载的小技巧,这种方式能有效的改进网站的访问速度。
大概原理是当用户鼠标经过链接的时候,会提前用 Ajax 的方式将网页预先加载好存入 cache,等用户点击的时候,用之前的 cache 直接渲染。
于是我还发了 Twitter 说这个事情:
Rails 内置的 Turbolinks 实际上有类似的 cache 机制,在用户来回点击页面的时候会利用 cache 提前渲染,只是没有在用户鼠标 hover 的时候进行预处理。
查了查,发现 Turblinks 的 Issue 里面也有讨论这个 turbolinks/turbolinks#313,仔细看找到了一个实现 参考,于是封装了一下,并做了改进实现了一个 Turbolinks 的扩展。
https://github.com/huacnlee/turbolinks-prefetch
同时我在实现里面额外调整了 Turbolinks 的 visit
动作,如果已经有 prefetch 的动作,会直接 render 不会再次请求页面。
如你所见,目前 Ruby China 已经开启了这个功能(香港服务器),在 prefetch 产生效果的时候,基本上页面打开犹如本地网页。
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();
当 Prefetch 请求的时候,将会额外发送 Purpose: prefetch
的 HTTP header,如果你需要特别忽略某些动作,你可以用到它。
比如更新阅读状态、访问量更新等动作:
class TopicsController < ApplicationController
def show
if request.headers["Purpose"] != "prefetch"
# 不在 prefetch 的时候更新访问量
@topic.increment_hit
end
end
end
默认情况下,Turbolinks Prefetch 将会对所有的链接开启行为。
除了下面这些情况:
target="_blank"
;data-remote
属性的链接;data-method
属性的链接;data-prefetch="false"
属性的链接;应该说大多数的默认情况下,你不需要处理,类似 Rails UJS 这样的默认行为已经在 Turbolinks Prefetch 处理好了。
于是你可以这样来对部分链接禁用 prefetch:
<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>
🎊 不要犹豫了,立即在你们已经有使用 Tubrolinks 的项目里面用起来吧,基本上是无缝支持。