This post is outdated. It covers SvelteKit's router before SvelteKit v1.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.