dreamland has a first-party react-router equivalent that supports most of the features react-router has.
It's designed to be a singleton component that is controlled via the router
export in dreamland/router
.
The router is constructed as a JSX component and routes are defined in JSX:
<div id="app">
<Router>
<Route show={<MainPage />} />
<Route show={<DocsLayout />} path="docs">
{docs.map(({ path, component }) => {
return <Route path={path} show={() => jsx(component, {})} />;
})}
</Route>
</Router>
</div>
Once a Router
component is created, the instance is exposed by the router
export.
The Router
automatically handles the popstate
event for history navigation.
It also exposes a route
function to simply change the current route without touching history and a navigate
function to both change the current route and commit it to history:
import { router } from "dreamland/router";
router.navigate("/"); // sent to history
Routes without a path
are treated as the "index.html" if they don't have any children.
If they have children, they're treated as a layout and the component in show
will get the child route's result assigned to this.outlet
.
If you assign a function to this["on:routeshown"]
, it'll get called once the route is shown.
dreamland's router is compatible with SSR and hydration, and exposes a ssgables
function to allow for easy prerendering.
It returns any route that doesn't have dynamic parameters in it.
let paths = router.ssgables();
let template = /* index.html ... */;
for (const [route, path] of paths) {
const rendered = await renderSsr(template, () => entry.default(route));
console.log(`prerendered: ${route}`);
let resolved = resolve("dist/static/" + path);
await mkdir(dirname(resolved), { recursive: true });
await writeFile(resolved, rendered);
}