Router

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

Special Routes

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.

SSR integration

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);
}