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
<br> 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.el
Type: HTMLElement
<br> Default: document.body
The DOM element to observe for in-viewport links to prefetch.
options.delay
Type: Number
<br> Default: 0
The amount of time each link needs to stay inside the viewport before being prefetched, in milliseconds.
options.limit
Type: Number
<br> Default: Infinity
The total requests that can be prefetched while observing the options.el
container.
options.throttle
Type: Number
<br> Default: Infinity
The concurrency limit for simultaneous requests while observing the options.el
container.
options.timeout
Type: Number
<br> Default: 2000
The requestIdleCallback
timeout, in milliseconds.
Note: The browser must be idle for the configured duration before prefetching.
options.timeoutFn
Type: Function
<br> Default: requestIdleCallback
A function used for specifying a timeout
delay.<br> 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
<br> 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>
<br> Default: [location.hostname]
A static array of URL hostnames that are allowed to be prefetched.<br> 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
or Function
or Array
<br> 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
<br> Default: None
An optional error handler that will receive any errors from prefetched requests.<br> By default, these errors are silently ignored.
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
or Array<String>
<br> Required: true
One or many URLs to be prefetched.
Note: Each
url
value is resolved from the current location.
isPriority
Type: Boolean
<br> Default: false
Whether or not the URL(s) should be treated as "high priority" targets.<br> 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
or Array<String>
<br> Required: true
One or many URLs to be prerendered.
Note: As prerendering using Speculative Rules API only supports same-origin at this point, only same-origin urls are accepted. Any non same-origin urls will return a rejected Promise.
Polyfills
quicklink
:
- Includes a very small fallback for requestIdleCallback
- Requires
IntersectionObserver
to be supported (see CanIUse). We recommend conditionally polyfilling this feature with a service like Polyfill.io:
<script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver"></script>
Alternatively, see the Intersection Observer polyfill.
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 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
]
});
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.<br> 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(err => {
// Handle own errors
});
</script>