demo · v141

Async Data Prep

When the user navigates to /post/42, the precommit handler prefetches the post body before the URL flips. The old page stays visible, with its scroll position and focus intact, until the data lands. Then the URL commits and the new view renders in one beat — no skeleton flash.

checking support…
simulated URL bar: /posts

the call

navigation.addEventListener("navigate", (e) => {
  if (!e.canIntercept || e.hashChange) return;
  e.intercept({
    // precommit runs while URL bar still shows previous page
    async precommitHandler() {
      const data = await fetchPostData(e.destination.url);
      e.destination.data = data;      // stash it for the commit phase
    },
    async handler() {
      // URL has now flipped; render with already-loaded data
      renderPost(e.destination.data);
    },
  });
});

why this angle

This is the React Router / Remix "loaders" pattern, the SvelteKit load() pattern, the TanStack Router beforeLoad pattern — the one all these libraries had to fake before. Without precommit, the new URL commits first and either renders a skeleton (showing flash) or asks the previous view to "stay" (forcing routers to manage two parallel render trees). The handler version had no way to express "don't commit yet, I'm fetching." Now it does. The log on this page shows exactly when the precommit phase ends and the URL flips — the gap is the prefetch.

see also