Prefetch: cyclewire/prefetch
Data fetched on intent, next to the action’s code. 0.5 kB brotli.
<a href="/products/42" cw-action="quickview" cw-prefetch="/api/products/42">Quick view</a>import { start } from 'cyclewire';import { prefetch } from 'cyclewire/prefetch';
start({ actions, plugins: [prefetch()] });export async function run({ element, fetch, signal }) { const response = await fetch(element.getAttribute('cw-prefetch'), { signal }); const product = await response.json(); // …}When the pointer reaches an element that binds an action, focus moves to it or a finger
lands on it, the plugin starts a GET of its cw-prefetch URL, while CycleWire fetches
the action’s module. The handler’s ctx.fetch works like fetch(), except that a plain
GET of that URL takes the response already on its way, once. The code and the data then
arrive together instead of one after the other.
- Only the page’s own origin. Markup never makes the browser ask another site for
anything; a
cw-prefetchelsewhere is ignored. - Only GET, only once.
ctx.fetchtakes a prefetched response for a request with no method, headers or body (asignalis fine), and only once: the next call fetches again. A response waits ten seconds at most, then it is dropped as stale. - Opting out stops it too. Nothing inside
cw-ignoreis prefetched, and neither is anything on an element withcw-preload="none", nor when the visitor asked to save data. - A failed prefetch costs nothing.
ctx.fetchthen asks again, and reports what that request returns.
An empty cw-prefetch names the URL the element itself leads to: its cw-get
(request), or a link’s href.
Only name URLs that are safe to fetch early: a GET must not change anything on the server, as HTTP intends.
prefetch(): the plugin.fetchAhead(input, init?): whatctx.fetchis, for code outside a handler.
The plugin uses the intent hook every plugin can use: see
writing a plugin. The full classic-script build installs it.