Open-source project
GoogleChromeLabs/quicklink avatar
GoogleChromeLabs/quicklink

GoogleChromeLabs/quicklink: Prefetching In-Viewport Links During Idle Time

⚡️Faster subsequent page-loads by prefetching in-viewport links during idle time

11,300 stars430 forksJavaScriptApache-2.0

At a glance

What is it?
quicklink is a small JavaScript library from GoogleChromeLabs that prefetches or prerenders links the user can already see, once the browser is idle. It is a drop-in speed layer for multi-page sites and React apps, with real constraints around connection checks and prerender limits.
Who is it for?
Adopt quicklink if you run a multi-page site or a React app with predictable link targets and want a small prefetch layer without writing your own Intersection Observer logic. Do not adopt it if your pages are mostly behind authentication, if most of your links are generated dynamically after the observer starts, or if you cannot tolerate speculative network traffic on metered connections.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 29 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The navigation latency problem quicklink targets

The README frames the goal narrowly: make navigations to subsequent pages load faster. That is a different problem from first-load performance. A site can have a fast initial paint and still feel slow, because every click starts a fresh document request, and the browser cannot begin that request until the user commits to the click. quicklink moves part of that work earlier by watching which links are visible and fetching their URLs before the user acts. The intended audience is teams running multi-page applications or server-rendered sites where link destinations are real URLs, and React single-page apps where routes map to chunks. The README also states the size target: under 2KB minified and gzipped. That number matters because quicklink runs on every page and competes with the content it is trying to speed up.

How quicklink decides what to fetch and when

The mechanism is a chain of gates, and each gate can stop a prefetch. First, quicklink detects links within the viewport using Intersection Observer. Second, it waits until the browser is idle using requestIdleCallback, with a default timeout of 2000ms. Third, it checks whether the user is on a slow connection via navigator.connection.effectiveType, or has data-saver enabled via navigator.connection.saveData. Only then does it prefetch, using <link rel=prefetch> or XHR, or prerender through the Speculation Rules API. The README notes that quicklink can switch to fetch() when the priority option is set to true, treating URLs in the observed container as high priority.

The option surface is where the real tuning lives. threshold defaults to 0 and controls what fraction of a link must enter the viewport. delay defaults to 0 and sets how long a link must stay visible. limit defaults to Infinity and caps total requests. throttle defaults to Infinity and caps concurrent requests. The listen() call returns a reset function that empties the active IntersectionObserver and the cache of already prefetched URLs, which the README suggests using between page navigations or after significant DOM changes. That return value is the part most integrations get wrong: without calling it, a client-side router can accumulate observers and a stale URL cache.

Installing quicklink and a first working setup

For a multi-page site, the README gives two paths. The npm route installs the package, and the unpkg route pulls the UMD build directly. Both are shown below exactly as the README presents them.

bash
npm install quicklink

After installing, the quickstart includes the UMD bundle from dist and calls listen() once. The README notes you can initialize this whenever you want, and gives an example of doing it after the load event fires so the prefetching does not compete with the initial page render.

html
<script src="dist/quicklink.umd.js"></script>
<script>
  quicklink.listen();
</script>

For bundler-based projects, quicklink exports named functions. The README shows both the standard entry point and a modern ES module build, quicklink.modern.mjs, described as smaller because it skips legacy transforms.

js
import {listen, prefetch} from 'quicklink';

For a React app, the README requires an extra package and a Webpack route manifest. The install command is npm install quicklink webpack-route-manifest --save-dev, and the manifest is generated as rmanifest.json, available at site_url/rmanifest.json or on window.__rmanifest. Routes are then wrapped with the withQuicklink HOC imported from quicklink/dist/react/hoc.js, passing an options object. After calling listen(), the expected result is that visible links are fetched during idle periods, which you can confirm in the browser network panel by watching for requests to link targets that were never clicked.

Where quicklink is the wrong tool

The connection checks cut both ways. On a slow connection or with data-saver enabled, quicklink skips prefetching, which is the correct default but means the library does nothing for exactly the users who feel latency most. If your audience is predominantly on constrained mobile networks, quicklink is largely inert.

The prerender path has a hard ceiling. The README states that the prerendering mode falls back to prefetching when the browser does not support prerender, and that once an element exits the viewport the speculationrules script is removed from the DOM. That removal is deliberate: the README says it makes it possible to exceed the limit of 10 prerenders imposed for the immediate and eager eagerness settings. This is a workaround for a browser-imposed cap, not a guarantee, and it depends on viewport churn to stay under the limit. Setting prerender: true on a page with many persistent visible links is the scenario most likely to hit that ceiling.

Prefetching is also speculative traffic. A user who scrolls a long article can trigger requests for every link that passes through the viewport. The limit and throttle options exist for this reason, and leaving both at their Infinity defaults on a link-dense page is a configuration mistake, not a library bug.

How quicklink differs from a service worker prefetch strategy

Workbox is the common alternative, and the difference is architectural. Workbox operates in a service worker: it intercepts fetch events and applies caching strategies, so prefetching is one entry in a broader runtime caching policy and the cached response persists across navigations. quicklink runs in the page. It has no cache of its own, no interception layer, and no offline behaviour. What it has is a much smaller integration surface: a script tag and a listen() call, versus registering and versioning a service worker.

That trade-off decides the choice. If you need offline support or a unified caching policy across asset types, quicklink is not a substitute for Workbox. If you want the navigation hint and nothing else, quicklink avoids the service worker lifecycle entirely. The README's own framing supports this: it calls the project a drop-in solution for prefetching based on the viewport, and says nothing about offline or cache management.

Maintenance status, upgrade cost and licence

The repository is not archived, and the last push was on 2026-09-01. Release history shows 3.0.2 on 2026-08-04, 3.0.1 on 2025-05-13, and 2.3.0 on 2023-03-30. That spacing is worth noting: the jump from 2.3.0 to 3.0.1 spans roughly two years, so the 3.x line is where recent work has landed and where the README's prerender and Speculation Rules material belongs. The package declares two runtime dependencies, route-manifest and throttles, plus a React peer dependency covering versions 16.8 through 19. The published files array contains only dist, so consumers get build output rather than source. Upgrades therefore mean tracking option semantics, and the README documents several options with non-obvious defaults that changed meaning across major versions. The licence is Apache-2.0, which permits commercial use and modification with the usual notice and patent terms; the repository ships a LICENSE file at the top level. This is a description of the licence identifier, not legal advice, and teams with redistribution requirements should read the LICENSE text themselves.

Editorial conclusion

Adopt quicklink if you run a multi-page site or a React app with predictable link targets and want a small prefetch layer without writing your own Intersection Observer logic. Do not adopt it if your pages are mostly behind authentication, if most of your links are generated dynamically after the observer starts, or if you cannot tolerate speculative network traffic on metered connections. Before shipping, verify three things in the README and the source: which build you are loading (dist/quicklink.umd.js, dist/quicklink.mjs, or dist/quicklink.modern.mjs), whether your target browsers support the Speculation Rules API if you set prerender: true, and how the returned reset function behaves on your router. quicklink is a client-side hint, not a caching layer; the server still has to answer every prefetch.

Frequently asked questions

What is quicklink and what does it do?

It is a JavaScript library that makes navigations to subsequent pages load faster by prefetching or prerendering in-viewport links during idle time. It detects visible links with Intersection Observer, waits for requestIdleCallback, and skips work on slow connections or when data-saver is enabled.

How do I install quicklink?

The README gives npm install quicklink for Node.js and npm users, or you can grab the build from unpkg.com/quicklink. After that, include the UMD bundle and call quicklink.listen(), or import the named listen and prefetch exports in a bundler setup.

How do I use quicklink on a page?

Include the dist bundle, then call quicklink.listen(). The README notes you can initialize it whenever you want, and shows an example that calls it inside a window load event listener. Once initialized, quicklink automatically prefetches URLs for links that are in the viewport during idle time.

Official sources

  1. GoogleChromeLabs/quicklink on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/googlechromelabs-quicklink.svg)](https://hysenlabs.com/projects/googlechromelabs-quicklink)