Simpler filesystem-based routing #5037
Replies: 27 comments 55 replies
-
Edit: a lot of people were confused by this example, so to be clear: As an example, this is what the default template might look like:
We no longer really need the |
Beta Was this translation helpful? Give feedback.
-
Just realised that while I really like this... -// src/routes/path/to/foo.ts
-import type { RequestHandler } from './__types/foo';
+// src/app/path/to/foo/index.ts
+import type { RequestHandler } from './$types'; ...it doesn't solve the problem we currently have around layout types not exposing child parameters. Layouts should be able to 'see' all the parameters of their children and parents, whereas leaves should only be able to see parameters of their parents: # file # visible parameters
src/app/
├ [a]/
│ ├ [b]/
│ │ ├ [c]/
│ │ │ ├ index.svelte a, b, c
│ │ │ └ layout.svelte a, b, c
│ │ ├ index.svelte a, b
│ │ └ layout.svelte a, b, c
│ ├ index.svelte a
│ └ layout.svelte a, b, c
├ [x]/
│ ├ [y]/
│ │ ├ [z]/
│ │ │ ├ index.svelte x, y, z
│ │ │ └ layout.svelte x, y, z
│ │ ├ index.svelte x, y
│ │ └ layout.svelte x, y, z
│ ├ index.svelte x
│ └ layout.svelte x, y, z
├ index.svelte
└ layout.svelte a, b, c, x, y, z For that we could introduce something like this: // src/app/path/to/foo/layout.ts
import type { RequestHandler } from './$types/all'; // or `$types/layout` or something |
Beta Was this translation helpful? Give feedback.
-
Honestly, I really love the current conventions. It's quite easy to understand any file under routes is, well... a route. I can totally understand newcomers confusion, but then again the docs are quite nice. My one gripe with going to folder based routes and using |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
The Problem I see with this approach of naming every file index is that it can become confusing which file you are editing at the moment. And you have a little more “boilerplate”. I think the current way of splitting the lib and pages folder quite good. And if you want to use components from the same folder, there is a way too. So I think the Proposal wouldn't do much, I think i t could confuse some more because for every folder you have to ask your self is this the final route or does it have another sub route. So to see this, you have to expand another folder. This may not be a Problem for smaller sites, but for larger sites if you are searching for something and every thing is named index.svelte and hidden in extra folders it could be a problem. The only thing I think should change is the labeling on the docs so That it 100% clear that every .svelte file is a route except for files with _ as prefix. |
Beta Was this translation helpful? Give feedback.
-
I guess it depends on if |
Beta Was this translation helpful? Give feedback.
-
So my initial thoughts here are mostly positive. While this would be a more verbose setup for smaller apps, I think that it definitely would help larger apps at scale, it's currently weird to figure out how to conventionally add components and other related code to a route (we've been adding a My only real issue with this proposal is actually this part:
While this is true, I'm not sure that this would actually be a good idea in practice. Today, you can quickly and easily visually grep for these special files in every route, which makes it much easier to find them when looking for them. With the new setup, it's very easy to miss these files in between others: What if we kept a single underscore prefix for these special files, like so: This would have three main advantages:
I also think it would make sense to do this for |
Beta Was this translation helpful? Give feedback.
-
tl;dr - I like the current filesystem-based router since it resembles web standards more closely. Though the router is magical in some ways (such as its implementation of rest parameters and back-end functions), a user of SvelteKit who is new to web development should walk away with a better understanding of routing that is closer to web standards, and the docs do a great job in educating these standards when the filesystem itself may not do so 100% intuitively. I want to highlight one of SvelteKit's principles:
Source: https://kit.svelte.dev/docs/web-standards I think we should use this as a guiding light when discussing the proposed filesystem-based routing. It's good to take inspiration from other frameworks, though keep in mind Next.js updated their filesystem-based routing around the concept of React 18's server components. Since this is Svelte and not React, I see the current implementation of SvelteKit is more similar to Nuxt in some ways that I find to be fair:
Having said that, perhaps taking inspiration from Nuxt by separating pages and endpoints with Disclaimer: I have not spent quality time using Svelte or SvelteKit yet, but I'm eager to watch these tools succeed. |
Beta Was this translation helpful? Give feedback.
-
I don't like this idea personally. I feel like I already have the issue of having a bunch of files called |
Beta Was this translation helpful? Give feedback.
-
What's the goal here? A clear "Here is what the benefits are" point has not been made. The only nail that seems to be getting hammered here is the corner case ambiguity between So there's those 2 points AND the removal of simple private scripts ( But no clearly stated or even visible consequential benefit. Ok one soft benefit. Therefore, I have to ask: What's the real point of introducing all these potential negatives? |
Beta Was this translation helpful? Give feedback.
-
My current setup has ton of Personally I like the new proposal, since it leads to less choice to made, every route now simply just Also, @pzuraq proposal looks best to me, it's keeping the file order and make special files more distinguishable. |
Beta Was this translation helpful? Give feedback.
-
My first thought on this proposal was, hmm...could be quite nice to have certain files colocated with appropriate route index files. But (as mentioned above) the loss of named route files seems a pretty big disadvantage to the current system. I'm not sure, other than colocation, what other real benefit this new system provides. |
Beta Was this translation helpful? Give feedback.
-
I like the more verbose but simpler directory-based routing proposal here. And I also like, (like might be a strong word) the special file prefixes used. Things I like about the directory-based approach:
Reasons I prefer to keep special file prefixes, (
I come primarily from a server-side background which means I care much more about the rendering pipeline from The reason I think this is related to this discussion is that I think layout endpoints, (which might have a different name) are coming soon and they're likely going to be a file that lives in the route directory. So, we'll need to both reserve namespace for it (e.g. by calling it p.s. When I was reading the Next.js RFC I was definitely hoping that Kit would follow-suit! |
Beta Was this translation helpful? Give feedback.
-
I like the proposal. The only two downsides I see are:
Edit: |
Beta Was this translation helpful? Give feedback.
-
I don't have a ton to add other than I get what you are going for but I much prefer the current setup. This seems like a lot of overhead and frankly more confusing just to fix a problem that doesn't seem like that big of a problem. All this to avoid a mistake a dev is likely to make once, look up what they did wrong, then fix it and never make that error again. As opposed to having 200 |
Beta Was this translation helpful? Give feedback.
-
@Rich-Harris in general I like to obsess about small details, e.g. route instead of index, and it's usually those small details which make a DX great. But the new proposal has some pros but also some cons or rather unanswered questions. The point is that the proposal doesn't feel significantly better at the current stage but we might get there. |
Beta Was this translation helpful? Give feedback.
-
@Rich-Harris mind to give us an update about which direction we are about to go? I ask bc I expect a huge rewrite of my codebase and I just want to be prepared... |
Beta Was this translation helpful? Give feedback.
-
This is a late addition to this discussion but VSCode has introduced a feature where you can nest files beneath other files as if they're folders. I think this solves the organization issue. The only issue with this is that there can be naming collisions since they are technically all in the same directory but I feel like it's a healthy rule of thumb to not have two components in your entire project with the same name unless necessary for some reason. I think needing everything to be a folder creates a very messy project and defeats one strength of svelte where a lot of the work for your component is all done in one file (meaning the markup templating, script, and styling is all handled in your |
Beta Was this translation helpful? Give feedback.
-
This is really annoying, from the example app. Why not call it |
Beta Was this translation helpful? Give feedback.
-
Just as another data point, Rust's module hierarchy used to adopt somewhat similar convention to this where certain modules need to be named by the names of their directory and have |
Beta Was this translation helpful? Give feedback.
-
I was working on a fork of sveltekit before named layouts were a thing, where the router works like this:
As you can see in the directory structure, layouts are no longer stored in the routes folder. They are now stored in the Routes are still stored in the vscode is smart enough to also include the path to the file when you've got two |
Beta Was this translation helpful? Give feedback.
-
TLDR: After reading the above comments, I recommend:
Explanation and description below:
|
Beta Was this translation helpful? Give feedback.
-
I don't know if it was and probably stupid, but whatever:
AND (ATTENTION HERE!) - files with underscores as route! Why? - Because by design, there should be more private files than route files - for each route, theoretically, there should be several private files. (Plus index files also exposed, of course. Alternatively, let's make index files with underscores too...?) Handicap (underline), let them have files that are fewer in number. |
Beta Was this translation helpful? Give feedback.
-
Here's a polarizing but hopefully helpful addition to the convo: Why not copy Next'js's new way of doing this? Some benefits:
Network effects of standardization can be incredibly beneficial to Kit's ecosystem. |
Beta Was this translation helpful? Give feedback.
-
After reading the proposals/reactions, the following is appreciated:
considering this and doing some tests:
<script>
// you will never have to remember the name you typed for the file.
import index from "./index.docs.svelte"
</script>
I leave some captures of everything.
I have no idea if |
Beta Was this translation helpful? Give feedback.
-
@Rich-Harris any news? You got pretty quiet. Folks need to know how you gonna decide... |
Beta Was this translation helpful? Give feedback.
-
In SvelteKit today,
src/routes/about.svelte
andsrc/routes/about/index.svelte
are equivalent. The consequence of that design decision is that every component or JavaScript module insidesrc/routes
is treated as a page or endpoint.This creates ambiguity (is one of
about.svelte
andabout/index.svelte
more 'correct'?), and confusion — I've seen cases where people innocently had things like this......not realising that they were creating a
/ComponentImportedByIndex
route. If you understand how Kit's routing works, it's easy enough to make files 'private' by prefixing them with_
(or putting them inside a_
-prefixed directory, or giving it some other filename that causesconfig.kit.routes
to returnfalse
), but this is ugly at best.I'd like to propose a scheme that I think is simpler, easier to learn, unambiguous, and more aesthetically pleasing. I realise this makes certain things more verbose, and would be an annoying breaking change for some people. Please take a breath before replying with something melodramatic! I strongly believe this will be a major improvement in the long run.
Proposal
Edit: now that the Next.js routing RFC is public, I can acknowledge that this is shamelessly stolen from there
The basic idea is to only use directories to define routes:
The hierarchy is immediately clearer than with
blog/index.svelte
andblog/[slug].svelte
, and we don't need to do anything weird with<ComponentImportedByBlogPage>
. Things naturally group together better.A weird thing we currently support is things like
src/routes/blog/index.json.js
to define/blog.json
, as an alternative to using page endpoints. In this model, you'd have to do this instead......which is more verbose, but much clearer (since
/blog
and/blog.json
are in fact separate routes, and you don't need to understand the hidden rules aroundfoo/index.ext.js
contractions).Today, the fact that any component can be a page means that we have to prefix layout and error components —
__layout.svelte
and__error.svelte
. With this proposal, that's no longer the case — we can do this instead:I find this much nicer. It does bring one downside though — we can no longer introduce new 'special' files without it being a breaking change (e.g. if we introduced route-level config, and someone had a
config.js
module, it would conflict). We would therefore need to think carefully about what names we wanted to reserve (e.g.hooks
,middleware
,config
etc alongsideindex
,layout
anderror
).Generated types
We currently take advantage of the
__
prefix by writing generated types to__types/[basename].d.ts
:If we were to get rid of
__layout
and__error
in favour oflayout
anderror
, we could change this to$types
, which looks nicer and is arguably more consistent with how$
is used elsewhere (__layout
and__error
are things you create, whereas__types
is something SvelteKit creates;$app
on the other hand contains partly generated modules, and$
is used generically for 'built-in alias' which./$types
qualifies as (since it usesrootDirs
which is a form of aliasing).Note also that it's always
./$types
, never./$types/foo
, which again is much nicer. This is another advantage of treating directories as routes rather than files.Named layouts
Named layouts would work as they currently do. (An earlier version of this comment suggested adding the
@foo
suffix to the directory instead ofindex@foo.svelte
etc, but that doesn't work because it would prevent child routes from bypassinglayout-foo
.) A nice benefit of moving to directories-as-routes is that we don't need to worry about escaping the@
character in cases where you do want it as part of your route (like@[username]
).Unresolved questions
index.{js,svelte}
orroute.{js,svelte}
, or something else? 'If a directory contains aroute
file it's a route' is a nice simple rule, thoughindex
is very conventional. Then again, the convention might work against us, since people will always want to do things likeutils/index.js
and not have it mean 'create autils
route'.route.{js,svelte}
, thensrc/app
might feel nicer thansrc/routes
, and in fact that's what I've used in the examples above. See Renamesrc/routes
tosrc/app
#3021 for a lengthy discussion on that topicBeta Was this translation helpful? Give feedback.
All reactions