This post is outdated for SvelteKit 1.x. It covers SvelteKit's router before SvelteKit 1.0.0-next.406.
The SvelteKit docs state that
At the heart of SvelteKit is a filesystem-based router. This means that the structure of your application is defined by the structure of your codebase — specifically, the contents of
src/routes
.
In this post, we will explore how SvelteKit's
filesystem-based router matches a requested
route to a page or an endpoint. SvelteKit transforms each route file in src/routes
into
a page or an endpoint. Conversely, SvelteKit needs to match a requested route to a route file. This
is called route matching.
A filesystem-based router makes route matching straightforward: the route can be interpreted as
the subpath in src/routes
and often there is only one matching route file. But what happens
when there are multiple matching route files? How does SvelteKit decide which route file it uses to
render a page or endpoint?
In this post, we look at a SvelteKit example and explore the rules that SvelteKit applies to decide which page or endpoint to serve. You will make the most out of this post if you follow along:
Duplicate route files are not permitted
When you have the example up and running, click route /green
in the preview.
SvelteKit matches this request to page src/routes/green.svelte
. This is the
filesystem-based router at work, which takes the route and looks for the corresponding route file
in src/routes
.
Now click route /red
. This time SvelteKit matches the request to page
src/routes/red/index.svelte
, which is equivalent to
src/routes/red.svelte
.
Create file src/routes/red.svelte
in the example and copy the content of file
src/routes/red/index.svelte
. You should see this error message in the terminal:
Rule 1: Duplicate route files are not permitted.
You cannot have both src/routes/red/index.svelte
and
src/routes/red.svelte
. SvelteKit won't let you.
Delete src/routes/red.svelte
and run
to restart the development server.
Matching against path segments
The SvelteKit router matches strings of route segments to path segments. Path segments inside
src/routes
can be static (.../static/...
) or dynamic (
.../[dynamic]/...
) with square brackets. Dynamic path segments match any string.
Static path segments require an exact match. The second rule describes the order in which
SvelteKit matches route segments to path segments:
Rule 2: SvelteKit matches route segments to path segments left to right.
Let's revisit the /red
route from before. Now that we know what dynamic path segments
are, we realize that there were three more candidate pages:
src/routes/[color].svelte
src/routes/[nocolor].svelte
src/routes/[colour]/index.svelte
These are not duplicate routes because the strings inside []
differ. We already know
from the previous section, that /red
is not rendered with any of the above candidate pages.
The reason is this rule:
Rule 3: Static path segments take precedence over dynamic path segments.
E.g., src/routes/green.svelte
(static) takes precedence over
src/routes/[color].svelte
(dynamic).
Alphabetical order of path segments
Let's look at route /blue
in the example. The candidate pages are:
src/routes/[color].svelte
src/routes/[nocolor].svelte
src/routes/[colour]/index.svelte
We need another rule to choose the page that is used to render
/blue
:
Rule 4: Index pages take precedence over non-index pages.
This is only relevant for pages that are not considered duplicate routes, e.g.,
src/routes/[colour]/index.svelte
takes precedence over
src/routes/[color].svelte
.
When matching route segment blue
, we can use this rule to eliminate the first two
candidate pages. This results in page src/routes/[colour]/index.svelte
being
rendered. You can confirm this by clicking on /blue
in the example.
Let's delete page src/routes/[colour]/index.svelte
in the example. To make the
workspace pick up this change, you need to click in the terminal and hit ⌃C
. Restart
the development server with
npm run dev
.
Now the two candidates for route /blue
are:
src/routes/[color].svelte
src/routes/[nocolor].svelte
A look at the rendered page reveals that the router used
src/routes/[color].svelte
. It did so because of this rule:
Rule 5: For two path segments of the same type, the first one in alphabetical order takes precedence.
E.g., src/routes/[color].svelte
takes precedence over
src/routes/[nocolor].svelte
because
color
comes before nocolor
in alphabetical order.
Matching with spread syntax
Let's look at route /color/blue
in the example. The candidate pages are:
src/routes/color/[color].svelte
src/routes/color/[...rest].svelte
[...rest]
in the second route is a dynamic path segment, which uses
spread syntax
and matches any path under /color
, no matter how deep. We refer to it as a spread
segment. The following rule clarifies, which page the router chooses to render
/color/blue
:
Rule 6: Dynamic path segments take precedence over spread segments.
E.g., src/routes/color/[color].svelte
takes precedence over
src/routes/color/[...rest].svelte
.
You can navigate to route /color/blue/dark
to see an example of a route that is
rendered with
src/routes/color/[...rest].svelte
.
Error pages
Last but not least, let's navigate to route /blue/dark
in the example. This time,
there are no candidate pages. What does the router do? It falls back to default error page
src/routes/+error.svelte
.
Note that as soon as there is one candidate page, including pages with spread segments, the
SvelteKit router does not fall back to an error page. This is what we observed for route
/color/blue/dark
in the previous section. It was rendered with
src/routes/color/[...rest].svelte
and not the default error page.
SvelteKit allows you to configure error pages more granular per directory and you can read up on how this works in the SvelteKit docs.