History base router for Svelte 3 SPA (Single Page Application).
$ npm install --save-dev svelte-spa-history-router
$ # or
$ yarn add svelte-spa-history-router
Import Router
and put into your main component (typically App.svelte).
For example:
# App.svelte
<script>
import { Router } from 'svelte-spa-history-router';
import Home from './Home.svelte';
import Article from './Article.svelte';
import NotFound from './NotFound.svelte';
const routes = [
{ path: '/', component: Home},
{ path: '/posts/(?<postId>.*)', component: Article},
{ path: '.*', component: NotFound},
];
</script>
<Router {routes}/>
Routes
require a routes
parameter.
routes
is a list of route objects. route object has path
, component
, and resolver
properties.
path
can be a regular expression. ^
and $
are automatically added when matching.component
is a SvelteComponent. there are no specific requirements for component.resolver
is a function to determine component dynamically (optional).Matching is simply performed in the order defined by routes
.
routeParams
is a store to contain matched value to current route.
For example:
# Article.svelte
<script>
import { routeParams } from 'svelte-spa-history-router';
</script>
<div class="article">
postId: {$routeParams.postId}
</div>
To navigate another page, link
and push
are available.
link
used with a a
tag like belowimport { link } from 'svelte-spa-history-router';
<a use:link href="/">Home</a>
push
used to navigate programaticallyimport { push } from 'svelte-spa-history-router';
<button on:click={ () => push('/') }>Go to Home</button>
Resolver is a mechanism to dynamically determine component and can be used in multiple use cases.
Example: code spliting (dynamic import)
<script>
import { Router } from 'svelte-spa-history-router';
const routes = [
{ path: '/', resolver: _ => import("Home.svelte") },
];
</script>
<Router {routes}/>
Example: dynamic routing and pass value to component props.
<script>
import { Router } from 'svelte-spa-history-router';
import Article from "./Article.svelte";
import NotFound from "./NotFound.svelte";
async function prefetchArticle(route) {
const article = await getArticle(route.params.postId);
if (article) {
// pass value to component props
route.props.article = article;
return Article;
} else {
return NotFound;
}
}
const routes = [
{ path: '/posts/(?<postId>.*)', resolver: prefetchArticle },
];
</script>
<Router {routes}/>
Example: guard
<script>
import { Router, redirect } from 'svelte-spa-history-router';
import Admin from "./Admin.svelte";
function adminGuard(route) {
if (!isAdmin($user)) {
return redirect("/");
}
return Admin;
}
const routes = [
{ path: '/', component: Home },
{ path: '/admin', resolver: adminGuard },
];
</script>
<Router {routes}/>
(Added in v2.0.0)
store to detect URL changes (including query string or hash)
<script>
import { currentURL } from "svelte-spa-history-router";
$: name = $currentURL.searchParams.get("name") || 'unknown';
</script>
<div>{ name }</div>
(Added in 2.1.0)
currentURL
store to detect URL changes PR6MIT License.
Generally, history-base router requires server-side routing so that user can open the direct link or reload.
For example, Nginx excerpt configuration is like bellow.
location / {
try_files $uri /index.html =404;
}
If you consider to use firebase hosting for your application, rewrite may be useful.
svelte-spa-history-router is inspired by svelte-spa-router and Svelte Router SPA.
If you don't need both history-base and regular expression support, I reccommend these powerful routers.