SuspenseRouter
interface SuspenseRouterProps extends PropsWithChildren {
history: SuspenseHistory<SuspenseLocationState>;
delay?: number;
}
A <SuspenseRouter> creates browserHistory using the browser's built-in history stack and uses provided delay to bail out from transitioning of a history change and render the corresponding fallback.
import { SuspenseRouter } from '@archibald/core';
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root'));
root.render(<SuspenseRouter>{/* The rest of your app goes here */}</SuspenseRouter>);
delay
delay prop defines amount in ms that your App will wait on a route change showing the UI from your previous URL before it shows the fallback element supplied for the next <Route> on the next URL.
Defaults to: 300ms.
Route prerendering (preload)
SuspenseRouter also drives route prerendering. When a link opts in via <RouterNavLink preload="…">, the router warms the target route so that its lazy chunk import and data fetches are kicked off before the user navigates. Following the link then resolves against the already-populated module and data caches, avoiding a loading fallback.
Strategies (app.router.prerender)
How the warming happens is set in your environment config:
| Strategy | What preload does | Cost |
|---|---|---|
'dom' (framework default) | renders the target route into a hidden container — a second, full render of your app tree | highest; duplicates the DOM while warming |
'data' (template default) | runs the matched routes' prefetch and preloads their code chunks, same as useRoutePrefetch | low; no second tree |
'off' | nothing — preload becomes a no-op | none |
// environment/common.ts
router: {
prerender: 'data'
}
Prefer 'data': it warms the same caches without the duplicated DOM. Use 'dom' only when you need the target route's render itself to run ahead of time (for example to trigger effects deep in the tree that populate caches the route's prefetch does not cover).
The framework default is still 'dom'; the shop template and newly scaffolded projects set 'data'. Flipping the framework default is a breaking change and is scheduled for the next major.
The hidden container ('dom' only)
The hidden container is transient: it is mounted only for the duration of the warming render and is retired as soon as warming settles. It is not kept alive until the user eventually navigates to the preloaded path. This matters because the container holds a second, full render of your app tree — leaving it mounted would duplicate every id and landmark in the DOM (and therefore in the accessibility and end-to-end test trees), which is a common source of "resolved to 2 elements" strict-locator failures. Retiring it once the caches are warm keeps the benefit without the duplicated DOM.
Prerendering only warms caches (chunks and fetched data). It does not keep the preloaded route's component instances mounted, so it should not be relied on for side effects that must persist across the actual navigation.