Search code examples
sveltesapper

Is there any other way to set route-regex, apart from file-names?


I'm currently hitting a limitation with routing in sapper. We need to create a route that matches two "slugs", like this [section(foo|bar)]. This works fine on *nix, but fails on Windows, due to the illegal | character. Next to this route, there's also a [slug] route on the same level, that matches all the rest. This is on purpose, as only foo and bar should render differently and they will also have sub-routes.

I thought about the following approaches:

  • Handle everything in the [slug] route, by checking if slug is either foo or bar and treating these cases differently. I'd rather not do this because code will get hard to read/maintain and there are sub-routes that should only apply to foo and bar
  • Create two folders foo and bar, instead of one named [section(foo|bar)]. This is undesirable, because it would mean lots of duplicated code
  • Prefix the route, eg. create a folder section, that contains a [slug] route. This seems like the least problematic option, but I'd prefer /foo as URL instead of /section/foo.

Is there any other possible option? Maybe a Windows compatible way of writing [section(foo|bar)]? Or a way to define routing RegEx, other than via filename?


Solution

  • Well, I only have an idea for you. and buyer beware... though I've tried; I've yet to get the basics of the following concept working in my project and ended up coming to the same [foo][bar] solution.

    Sapper has a concept called spread routes. They are denoted using the [...slug].svelte file/router convention.

    The idea is that using the ...spread operator in the filename informs the router that this param should be treated as an array of objects capable of holding elements. The router is supposed to .join('/') all of the array elements to form the route...

    • from the Sapper docs

      If you don't want to create several folders to capture more than one parameter like [year]/[month]/..., or if the number of parameters is dynamic, you can use a spread route parameter. For example, instead of individually capturing /blog/[slug]/[year]/[month]/[day], you can create a file for /blog/[...slug].svelte and extract the params like so:

    <!-- src/routes/blog/[...slug].svelte -->
    <script context="module">
        export async function preload({ params }) {
            let [slug, year, month, day] = params.slug;
    
            return { slug, year, month, day };
        }
    </script>
    

    The idea I have for you is to leverage spread routing so you bypass the pipe | character problem by shimming your query in as one of those objects.