Skip to content

Commit e2277b1

Browse files
committed
Update for current status / SvelteKit
1 parent cfd7670 commit e2277b1

File tree

1 file changed

+61
-55
lines changed

1 file changed

+61
-55
lines changed

text/0000-sapper-routing.md renamed to text/0000-routing.md

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
- RFC PR: (leave this empty)
33
- Svelte Issue: (leave this empty)
44

5-
# Refactoring out Sapper's Routing
5+
# Refactoring out SvelteKit's Routing
66

77
## Summary
88

9-
Split Sapper's routing functionality into a standalone library and make it possible to use Sapper's routing outside of Sapper.
9+
Split SvelteKit's routing functionality into a standalone library and make it possible to use SvelteKit's routing outside of SvelteKit.
1010

1111
## Motivation
1212

1313
Benefits include:
1414

15-
* Making it possible to use Sapper's routing outside of Sapper. The routing component should be able to be used in a client-side only application
16-
* Making Sapper's routing more configurable. E.g. the user may wish to set a custom header on a certain route. We could expose the router component in the application and allow the user to set configuration on a per-route basis along the lines of `router.header('/[list]/[page]', {'Cache-Control': max-age=600'})`
15+
* Making it possible to use SvelteKit's routing outside of SvelteKit. The routing component should be able to be used in a client-side only application
16+
* Making SvelteKit's routing more configurable. E.g. the user may wish to set a custom header on a certain route. We could expose the router component in the application and allow the user to set configuration on a per-route basis along the lines of `router.header('/[list]/[page]', {'Cache-Control': max-age=600'})`
1717
* Other requests users have for configuring the router include [routes aliases](https://github.com/sveltejs/sapper/issues/1450) and [configuring trailing slashes](https://github.com/sveltejs/sapper/issues/519), which we could expose APIs for as well
1818
* Improved testability. Right now to test routing functionality you need a sample application and all tests are integration tests
19-
* I believe it would become possible to make it such that Sapper's routing can be used with or without generating it from the file system though this is perhaps not a primary goal.
20-
* Finally, Sapper's routing and Routify are quite similar. It may be possible to combine these two systems if everyone involved were open to such a possibility. I think it'd be good for the Svelte community to have a single solution because it means that solution would get more developer support than two individual solutions. Right now [there are many Svelte routing solutions](https://twitter.com/lihautan/status/1315482668440580096?s=19).
19+
* I believe it would become possible to make it such that SvelteKit's routing can be used with or without generating it from the file system though this is perhaps not a primary goal.
20+
* Finally, SvelteKit's routing and Routify are quite similar. It may be possible to combine these two systems if everyone involved were open to such a possibility. I think it'd be good for the Svelte community to have a single solution because it means that solution would get more developer support than two individual solutions. Right now [there are many Svelte routing solutions](https://twitter.com/lihautan/status/1315482668440580096?s=19).
2121

2222
## Detailed design
2323

@@ -29,78 +29,91 @@ This could be split up into multiple PRs that are smaller and easier to review.
2929

3030
Remove need to specify CSS files in routing components.
3131

32-
Update: this has been completed in [#1508](https://github.com/sveltejs/sapper/pull/1508)
32+
Update: this was completed in [#1508](https://github.com/sveltejs/sapper/pull/1508).
3333

3434

3535
#### Step 2
3636

37-
Put all routing information in a single routing component. Historically it has been split between `start` and `app`.
37+
Put all routing information in a single routing component. Historically, in Sapper, it has been split between `start` and `app`.
3838

39-
Update: this has been largely completed in [#1434](https://github.com/sveltejs/sapper/pull/1434). We can probably still clean up the prefetching code, etc.
39+
Update: this has basically been completed with the router now living `packages/kit/runtime/internal/router`
4040

4141

4242
#### Step 3
4343

44-
Add an API to register routes and make the generated code call the router rather than the router calling the generated code.
44+
Parse routes at runtime to simplify API.
4545

46-
Right now, the generated `manifest-client.mjs` contains something like:
46+
Right now, the generated `manifest.js` contains something like:
4747

4848
```
49-
export const components = [
50-
{
51-
js: () => import("../../../routes/index.svelte")
52-
},
53-
{
54-
js: () => import("../../../routes/[list]/[page].svelte")
55-
}
49+
const components = [
50+
() => import("/_app/routes/index.svelte.js"),
51+
() => import("/_app/routes/about.svelte.js"),
52+
() => import("/_app/routes/item/[id].svelte.js"),
53+
() => import("/_app/routes/user/[name].svelte.js")
5654
];
5755
58-
export const routes = (d => [
56+
const d = decodeURIComponent;
57+
const empty = () => ({});
58+
59+
export const pages = [
5960
{
6061
// index.svelte
6162
pattern: /^\/$/,
62-
parts: [
63-
{ i: 0 }
64-
]
63+
params: empty,
64+
parts: [components[0]]
6565
},
66+
67+
{
68+
// about.svelte
69+
pattern: /^\/about\/?$/,
70+
params: empty,
71+
parts: [components[1]]
72+
},
73+
6674
{
67-
// [list]/[page].svelte
68-
pattern: /^\/([^/]+?)\/([^/]+?)\/?$/,
69-
parts: [
70-
null,
71-
{ i: 1, params: match => ({ list: d(match[1]), page: d(match[2]) }) }
72-
]
75+
// item/[id].svelte
76+
pattern: /^\/item\/([^/]+?)\/?$/,
77+
params: (m) => ({ id: d(m[1])}),
78+
parts: [components[2]]
79+
},
80+
81+
{
82+
// user/[name].svelte
83+
pattern: /^\/user\/([^/]+?)\/?$/,
84+
params: (m) => ({ name: d(m[1])}),
85+
parts: [components[3]]
7386
}
74-
])(decodeURIComponent);
87+
];
7588
```
7689

77-
78-
It would be nice to invert this such that the generated code calls the router instead of the router importing the generated code:
90+
This API is a bit complex. However, it could be greatly simplified by making the route parsing be part of the router runtime instead of happening at compile time:
7991

8092
```
81-
import router from 'router';
82-
83-
router.register({
84-
route: /^\/$/,
85-
component: () => import("../../../routes/index.svelte")
86-
});
87-
router.register({
88-
route: /^\/([^/]+?)\/([^/]+?)\/?$/,
89-
params: match => ({ list: d(match[1]), page: d(match[2]) }),
90-
component: () => import("../../../routes/[list]/[page].svelte")
93+
const pages = {
94+
'/': () => import("../../../routes/index.svelte"
95+
'/[list]/[page]': () => import("../../../routes/[list]/[page].svelte"
96+
}
97+
98+
const router = new Router({
99+
base: paths.base,
100+
host,
101+
pages,
102+
ignore
91103
});
92104
```
93105

94-
This API is a bit complex. However, it could be greatly simplified by making the route parsing be part of the router runtime instead of happening at compile time:
106+
The `pattern` is needed on the server-side too, so we will still have to include it in the manifest.
95107

96-
```
97-
import router from 'router';
108+
#### Step 4
98109

99-
router.register('/', () => import("../../../routes/index.svelte"));
100-
router.register('/[list]/[page]', () => import("../../../routes/[list]/[page].svelte"));
101-
```
110+
Refactor out routes generation into separate plugin. Publish components separately.
102111

103-
#### Step 4
112+
Review the API and make sure we like it. There's probably some minor cleanup to do before exposing the routing API more broadly
113+
114+
We could potentially have a library for the core routing functionality. And then a second for the file-system-based routes generator.
115+
116+
#### Step 5 - Optional
104117

105118
Unify the client and server routing APIs.
106119

@@ -113,13 +126,6 @@ The server manifest also differs in a number of unnecessary ways:
113126

114127
We can remove the unnecessary differences. We will still need different client-side and server-side router instantiations registering their respective components, but they can utilize the same `router.register` API. On the client-side we can call `router.navigate`. On the server-side, we can just ask the router to return the registered component for a given route and let `get_page_handler` continue to handle it as it does today.
115128

116-
#### Step 5
117-
118-
Refactor out routes generation into separate plugin. Publish components separately.
119-
120-
Review the API and make sure we like it. There's probably some minor cleanup to do before exposing the routing API more broadly
121-
122-
We could potentially have a library for the core routing functionality. And then a second for the file-system-based routes generator.
123129

124130
## How we teach this
125131

0 commit comments

Comments
 (0)