API
quicklink.listen(options)
Returns: Function
A "reset" function is returned, which will empty the active IntersectionObserver
and the cache of URLs that have already been prefetched or prerendered. This can be used between page navigations and/or when significant DOM changes have occurred.
options.prerender
- Type:
Boolean
- Default:
false
Whether to switch from the default prefetching mode to the prerendering mode for the links inside the viewport.
Note: The prerendering mode (when this option is set to true) will fallback to the prefetching mode if the browser does not support prerender.
options.prerenderAndPrefetch
- Type:
Boolean
- Default:
false
Whether to activate both the prefetching and prerendering mode at the same time.
options.delay
- Type:
Number
- Default:
0
The amount of time each link needs to stay inside the viewport before being prefetched, in milliseconds.
options.el
- Type:
HTMLElement|NodeList<A>
- Default:
document.body
The DOM element to observe for in-viewport links to prefetch or the NodeList of Anchor Elements.
options.limit
- Type:
Number
- Default:
Infinity
The total requests that can be prefetched or prerendered while observing the options.el
container.
options.threshold
- Type:
Number
- Default:
0
The area percentage of each link that must have entered the viewport to be fetched, in its decimal form (e.g. 0.25 = 25%).
options.throttle
- Type:
Number
- Default:
Infinity
The concurrency limit for simultaneous requests while observing the options.el
container.
options.timeout
- Type:
Number
- Default:
2000
The requestIdleCallback
timeout, in milliseconds.
Note: The browser must be idle for the configured duration before prefetching.
options.timeoutFn
- Type:
Function
- Default:
requestIdleCallback
A function used for specifying a timeout
delay.
This can be swapped out for a custom function like networkIdleCallback (see demos).
By default, this uses requestIdleCallback
or the embedded polyfill.
options.priority
- Type:
Boolean
- Default:
false
Whether or not the URLs within the options.el
container should be treated as high priority.
When true
, quicklink will attempt to use the fetch()
API if supported (rather than link[rel=prefetch]
).
options.origins
- Type:
Array<String>
- Default:
[location.hostname]
A static array of URL hostnames that are allowed to be prefetched.
Defaults to the same domain origin, which prevents any cross-origin requests.
Important: An empty array ([]
) allows all origins to be prefetched.
options.ignores
- Type:
RegExp
orFunction
orArray
- Default:
[]
Determine if a URL should be prefetched.
When a RegExp
tests positive, a Function
returns true
, or an Array
contains the string, then the URL is not prefetched.
Note: An
Array
may containString
,RegExp
, orFunction
values.
Important: This logic is executed after origin matching!
options.onError
- Type:
Function
- Default: None
An optional error handler that will receive any errors from prefetched requests.
By default, these errors are silently ignored.
options.hrefFn
- Type:
Function
- Default: None
An optional function to generate the URL to prefetch. It receives an Element as the argument.
quicklink.prefetch(urls, isPriority)
Returns: Promise
The urls
provided are always passed through Promise.all
, which means the result will always resolve to an Array.
Important: You much
catch
you own request error(s).
urls
- Type:
String
orArray<String>
- Required:
true
One or many URLs to be prefetched.
Note: Each
url
value is resolved from the current location.
isPriority
- Type:
Boolean
- Default:
false
Whether or not the URL(s) should be treated as "high priority" targets.
By default, calls to prefetch()
are low priority.
Note: This behaves identically to
listen()
'spriority
option.
quicklink.prerender(urls)
Returns: Promise
Important: You much
catch
you own request error(s).
urls
- Type:
String
orArray<String>
- Required:
true
One or many URLs to be prerendered.
Note: Speculative Rules API supports same-site cross origin Prerendering with opt-in header.
Polyfills
quicklink
:
- Includes a very small fallback for requestIdleCallback
- Requires
IntersectionObserver
to be supported. This is supported in all modern browsers, however you can use the Intersection Observer polyfill to support legacy browsers if needed.
Recipes
Set a custom timeout for prefetching resources
Defaults to 2 seconds (via requestIdleCallback
). Here we override it to 4 seconds:
quicklink.listen({
timeout: 4000,
});
Set a specific Anchor Elements NodeList to observe for in-viewport links
Defaults to document
otherwise.
quicklink.listen({
el: document.querySelectorAll('a.linksToPrefetch'),
});
Set the DOM element to observe for in-viewport links
Defaults to document
otherwise.
quicklink.listen({
el: document.getElementById('carousel'),
});
Programmatically prefetch()
URLs
If you would prefer to provide a static list of URLs to be prefetched, instead of detecting those in-viewport, customizing URLs is supported.
// Single URL
quicklink.prefetch('2.html');
// Multiple URLs
quicklink.prefetch(['2.html', '3.html', '4.js']);
// Multiple URLs, with high priority
// Note: Can also be use with single URL!
quicklink.prefetch(['2.html', '3.html', '4.js'], true);
Programmatically prerender()
URLs
If you would prefer to provide a static list of URLs to be prerendered, instead of detecting those in-viewport, customizing URLs is supported.
// Single URL
quicklink.prerender('2.html');
// Multiple URLs
quicklink.prerender(['2.html', '3.html', '4.js']);
Set the request priority for prefetches while scrolling
Defaults to low-priority (rel=prefetch
or XHR). For high-priority (priority: true
), attempts to use fetch()
or falls back to XHR.
Note: This runs
prefetch(..., true)
with URLs found within theoptions.el
container.
quicklink.listen({priority: true});
Specify a custom list of allowed origins
Provide a list of hostnames that should be prefetch-able. Only the same origin is allowed by default.
Important: You must also include your own hostname!
quicklink.listen({
origins: [
// add mine
'my-website.com',
'api.my-website.com',
// add third-parties
'other-website.com',
'example.com',
// ...
],
});
Allow all origins
Enables all cross-origin requests to be made.
quicklink.listen({
origins: true,
// or
origins: [],
});
Custom Ignore Patterns
These filters run after the origins
matching has run. Ignores can be useful for avoiding large file downloads or for responding to DOM attributes dynamically.
// Same-origin restraint is enabled by default.
//
// This example will ignore all requests to:
// - all "/api/*" pathnames
// - all ".zip" extensions
// - all <a> tags with "noprefetch" attribute
//
quicklink.listen({
ignores: [
/\/api\/?/,
uri => uri.includes('.zip'),
(uri, elem) => elem.hasAttribute('noprefetch'),
],
});
You may also wish to ignore prefetches to URLs which contain a URL fragment (e.g. index.html#top
). This can be useful if you (1) are using anchors to headings in a page or (2) have URL fragments setup for a single-page application, and which to avoid firing prefetches for similar URLs.
Using ignores
this can be achieved as follows:
quicklink.listen({
ignores: [
uri => uri.includes('#'),
// or RegExp: /#(.+)/
// or element matching: (uri, elem) => !!elem.hash
],
});
Custom URL to prefetch via hrefFn callback
The hrefFn method allows to build the URL to prefetch (e.g. API endpoint) on the fly instead of the prefetching the href
attribute URL.
quicklink.listen({
hrefFn(element) {
return element.href.replace('html', 'json');
},
});
Browser Support
The prefetching provided by quicklink
can be viewed as a progressive enhancement. Cross-browser support is as follows:
- Without polyfills: Chrome, Safari ≥ 12.1, Firefox, Edge, Opera, Android Browser, Samsung Internet.
- With Intersection Observer polyfill ~6KB gzipped/minified: Safari ≤ 12.0, IE11
- With the above and a Set() and Array.from polyfill: IE9 and IE10. Core.js provides both
Set()
andArray.from()
shims. Projects like es6-shim are an alternative you can consider.
Certain features have layered support:
- The Network Information API, which is used to check if the user has a slow effective connection type (via
navigator.connection.effectiveType
) is only available in Chrome 61+ and Opera 57+ - If opting for
{priority: true}
and the Fetch API isn't available, XHR will be used instead.
Using the prefetcher directly
A prefetch
method can be individually imported for use in other projects.
This method includes the logic to respect Data Saver and 2G connections. It also issues requests thru fetch()
, XHRs, or link[rel=prefetch]
depending on (a) the isPriority
value and (b) the current browser's support.
After installing quicklink
as a dependency, you can use it as follows:
<script type="module">
import {prefetch} from 'quicklink';
prefetch(['1.html', '2.html']).catch(error => {
// Handle own errors
});
</script>