kit icon indicating copy to clipboard operation
kit copied to clipboard

allow `config.kit.files.routes` to be an array of directories

Open sidvishnoi opened this issue 2 years ago • 9 comments

Describe the problem

We have a multi-tenant SvelteKit project, with a directory structure like following:

src/routes/
 - index.svelte
 - about.svelte
 - terms.svelte
 - [...project1]/
    - index.svelte
 - [...project2]/
    - about.svelte

Here, we've many common routes (index, about, terms). Each project can override the common routes with a few of their custom routes (like project1 has its own index.svelte but uses the common about.svelte; and project2 has a different about.svelte but uses the common index and terms page.

Before we had the new routing system (https://github.com/sveltejs/kit/discussions/5774), we could filter out specific files from routes directory to be considered for routing using the config.kit.routes function. This was done based on build-time env variables like following:

   routes(filepath) {
      const currentProject = process.env.PROJECT_ID;
      // Exclude special folder that doesn't match current project.
      const re = /^\/\[\.\.\.(project1|project2)\]/;
      if (re.test(filepath) && filepath.match(re)[1] !== currentProject) {
        return false;
      }

      // If we've a matching route in currentProject-specific folder, exclude the common
      // filepath route. We'll end up using currentProject-specific one as `params[currentProject]` can
      // be an empty string, which SvelteKit router matches.
      // This does mean `/anything/foo` as well as `/foo resolve to same page, 
      // but we can exclude `/{anything}/foo` using route params. Hacky, but works.
      const specialRoute = path.join(`src/routes/[...${currentProject}]`, filepath);
      return !existsAsFile(specialRoute);
   },

Now, the config.kit.routes option has been removed and we can't upgrade to newer versions without major changes to our approach.

Describe the proposed solution

  • Bring back config.kit.routes option.
  • Support multiple directory in config.kit.files.routes, which can support overrides like above. This is arguably a niche use-case, but would love if this can be supported.

Alternatives considered

We can create multiple top-level routes directories and symlink/hardlink the common routes to project-specific directory, while avoiding the existing non-symlink project-specific files, to have a directory structure like:

src/
  - routes.common/
    - index.svelte
    - about.svelte
    - terms.svelte
  - routes.project1/
    - index.svelte
    - about.svelte <symlink>
    - terms.svelte <symlink>
  - routes.project2/
    - index.svelte <symlink>
    - about.svelte
    - terms.svelte <symlink>

But this might cause confusion, where we update one file and it unexpectedly ends up updating other file too. Also, it will require us to delete the symlink and create a regular file when we want to override a route.

Importance

would make my life easier

Additional Information

No response

sidvishnoi avatar Aug 18 '22 11:08 sidvishnoi

Using routes for this is the sort of creative hackery that I very much enjoy. That said, it is hackery, and not a good reason by itself to reinstate the feature, I think.

What about this as an alternative? The basic idea is that you start SvelteKit (dev or build) like so...

PROJECT=project-1 pnpm dev

...and it creates a new routes directory there and then that combines the default files with the overrides. If no PROJECT is specified, it defaults to using src/routes.

Obviously I'm glossing over some details (e.g. you would probably want to watch the src/project-{n} directories during dev to update the generated routes directory) but this feels like a better match between intention and outcome than abusing rest parameters, which feels like it will inevitably cause gotchas further down the line.

Rich-Harris avatar Aug 18 '22 15:08 Rich-Harris

Thanks for the quick reply, @Rich-Harris! Indeed, it is hackery.

What about this as an alternative?

Yeah, that's the alternative I was considering (but with symlinks instead and not removing the project dir as it contains the override routes).

Though, what are your thoughts on supporting multiple folders in config.kit.files.routes?

sidvishnoi avatar Aug 18 '22 15:08 sidvishnoi

I can see it being a potentially quite valuable addition. It would add some more moving parts though, and the aftershock of #5748 is still reverberating through the codebase — lots of small follow-up work that needs to happen — and so now would be a challenging time to make those sorts of changes.

Once we ship 1.0 and have a more stable base work on top of I think we should revisit this.

Rich-Harris avatar Aug 18 '22 16:08 Rich-Harris

@Rich-Harris Can this be re-visited now that it's post-1.0 😊 ?

I have a similar use case, but nothing as exotic as having two projects - I'm generating a static site with adapter-static, but I also have an admin route that I'd like to exclude during the build. Right now the workaround is to rm -rf src/routes/admin to build, but that's pretty hacky.

pyronaur avatar Jun 15 '23 15:06 pyronaur

I have a similar use case - I want to be able to share routes between multiple projects. For example, let's say I create a Blog package that I want to include in multiple projects with the minimum boilerplate/wiring-up possible (and ultimately to be able to share that package with the public).

All the components and source files in $lib come over nicely, that's great. But the routes need to be re-created in some way for each project that uses the package. And while for a simple package like a Blog that isn't too much hassle, for something more complex like an e-commerce system, re-creating the routes - and dealing with updates to the shared packages - for each project becomes a problem.

A solution like OP is describing would be incredibly helpful and I think would be a real boon for the Svelte ecosystem as we would be able to share share full functionality more easily and allow for more "batteries included" projects to be built on top of SvelteKit.

freeborough avatar Jun 19 '23 16:06 freeborough

I am migrating from express where I have a user module that handles all my user logic, routes, etc. and I just "plug in" to each project. I was looking for how to do this and stumbled on this thread. Being able to slice applications vertically and share them between projects. At present I can share the logic, and the lib components, but I have to recreate routes and pages which is a pain.

danielbayley80 avatar Jul 13 '23 18:07 danielbayley80

I've a similar use case and such a possibility would be very helpful: I'm creating a backoffice application and as always there's a lot of similar screens in those that directly depend on the data model. In order to save time in the long run I'm setting things up to use code generation in all layers on my stack, which includes generating svelte pages and components. For the later it is quite simple to have one $lib directory and one $generated, though the same doesn't apply to routes.

I would like to be able to have two folders (e.g. src/routes and generated/routes) which contain the manually defined and automatically generated routes. Currently I don't seem to find an efficient way to do so with SvelteKit.

Just found a workaround: put all generated routes in a (generated) group which serves only the purpose to have them under a single folder so its content can be ignored by git. Not ideal but seem to do the job for now.

dcarniel-ipepper avatar Feb 05 '24 14:02 dcarniel-ipepper

Is this by any chance implemented in SvelteKit 2.0?

lunatiqqc avatar Feb 06 '24 07:02 lunatiqqc

Is this by any chance implemented in SvelteKit 2.0?

I don't think so, I'm using Svelte 2.4.3 and the config.kit.files.routes options is a string.

dcarniel-ipepper avatar Feb 06 '24 07:02 dcarniel-ipepper