prefetch
Warm a large asset into the browser cache before it is needed, without spending the user's data behind their back.
The key fact: if a Service Worker does cache-first on same-origin GETs, simply fetch-ing a
URL once puts it in CacheStorage. Any later request for the same URL hits the cache and works
offline. Prefetching therefore needs no special downloader: just pull the bytes in.
API
| Function | Description |
|---|---|
whenIdle(callback, options?) |
Run when the browser is idle; returns a cancel function |
networkAllowsDownload(options?) |
May we spend the user's data right now? |
isUrlCached(url) |
Is this URL already in CacheStorage? |
prefetchUrl(url) |
Pull one URL into cache; skips if cached, fails silently |
prefetchUrls(urls, options?) |
Same for a list, serially |
prefetchWhenIdle(urls, options?) |
The three combined: allowed → idle → serial prefetch. Non-blocking |
Options
| Option | Applies to | Description | Default |
|---|---|---|---|
timeout |
whenIdle |
Max wait for requestIdleCallback (ms) |
8000 |
fallbackDelay |
whenIdle |
Delay when requestIdleCallback is missing (ms) |
2500 |
optOutKey |
network allowance | localStorage key; any value means the user turned prefetch off | — |
slowTypes |
network allowance | effectiveType values considered too slow |
['slow-2g', '2g'] |
serviceWorkerMessage |
prefetchUrls |
Message type to hand the list to a controlling SW |
— |
Example
import { prefetchWhenIdle, isUrlCached } from 'ranuts';
prefetchWhenIdle(modelFiles, {
optOutKey: 'disable_model_prefetch',
serviceWorkerMessage: 'precache-models',
});
// Later: is it already local? (probe the file that finishes downloading last)
const ready = await isUrlCached(modelFiles.at(-1));Notes
- Prefetching spends someone else's data.
networkAllowsDownloadrefuses under Data Saver, on a slow connection, or when the user opted out. - Unknown means allowed. The Network Information API does not exist in Safari or Firefox; being unable to read the connection is not a reason to never prefetch.
- Lists are fetched serially: saturating the pipe would slow down the page the user is actually looking at.
- Prefer the Service Worker path. A SW using
event.waitUntilkeeps downloading across navigations; a main-thread fetch dies when the user clicks away. Without a controlling SW it falls back automatically. - Probe the largest file when checking whether a set is cached, or a half-finished download reads as complete.
- Failures are silent by design: a failed prefetch just means the real load downloads later.