sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.4k stars 1.88k forks source link

Separate route deployment #5643

Open andreiborisov opened 2 years ago

andreiborisov commented 2 years ago

Describe the problem

We're evaluating SvelteKit as our framework of choice, but we need to control which page will be rendered on which route server-side with answers from our API (dynamically construct the route map). Currently:

  1. There is no way to build and deploy a single route without rebuilding and redeploying the whole app.
  2. The whole route map is static meaning it needs to be known at compile time.

Describe the proposed solution

As far as I understand a hydrated SvelteKit app is not aware what is rendered on a new route already, since the component is loaded during the navigation. So it seems implementing dynamic routing support would be at least somewhat feasible.

The proposed solution: a single route build target which can be deployed separately while working the same as a single deployment.

Alternatives considered

  1. Generating SvelteKit project structure dynamically and redeploying the whole app — this is somewhat okay, but it won't scale nicely for our use case, unfortunately.
  2. Using vanilla Svelte — would require reimplementing all of the niceties of SvelteKit ourselves, which is a huge effort.

Importance

I cannot use SvelteKit without it

Additional Information

Although a big part SvelteKit' appeal is its simple file based routing structure, dynamic routing is an important use case, especially for enterprise applications.

Rich-Harris commented 2 years ago

Can you use rest routes along with dynamically imported components?

andreiborisov commented 2 years ago

Thank you for the fast answer, Rich❤️

Hm, haven't thought of that! Is it possible to do dynamic importing inside the load function, so it happens during prefetch?

elliott-with-the-longest-name-on-github commented 2 years ago

@andreiborisov

Yes it is, using await import (if you need one file) or import.meta.glob (from Vite) if you need more. Though I'd be more curious of your use case, as this sometimes isn't the best way to do it.

Funny you ask this, as Rich and I actually had a conversation about it earlier today. Here are a few screenshots demonstrating a significant "gotcha" of await import with Vite (hopefully Rich doesn't shoot me for screenshotting the super-secret maintainers' chat 😉):

Screenshot_20220720-192146.png

Rich-Harris commented 2 years ago

Yeah — like the screenshotted convo suggests, it's better if you're importing from a shorter list of components than a longer list, but it'll work either way. The one caveat is that SvelteKit can't know which of the candidates were actually imported during load (at least, not yet — maybe there's a smart way to do it), so as a consequence it has to follow all the dynamic imports and include any CSS they use in order to avoid FOUC.

What I mean by that is that if you have components like these...

src/lib/components/Red.svelte
src/lib/components/Green.svelte
src/lib/components/Blue.svelte

...and a load function like this...

<script context="module">
  export async function load(event) {
    const colour = ['Red', 'Green', 'Blue'][Math.floor(Math.random() * 3)];
    const module = await import(`$lib/components/${colour}.svelte`);

    const loaded = await module.load?.(event) ?? {};

    return {
      ...loaded,
      props: {
        props: loaded.props,
        module
      }
    };
  }
</script>

<script>
  export let props;
  export let module;
</script>

<svelte:component this={module.default} {...props} />

...then the CSS on the page will include all these...

.red { color: red }
.green { color: green }
.blue { color: blue }

...even though only one of them actually got rendered.

andreiborisov commented 2 years ago

Though I'd be more curious of your use case, as this sometimes isn't the best way to do it.

@tcc-sejohnson We're building a DAO that focuses on software development. The idea is to provide ready-made software modules for the members, so they can quickly build and launch products on top of it. The products will be defined entirely at a state level of those generic modules, hence the need to control routes server-side and deploy them separately.

In this case the API will be telling the frontend which Svelte component should be rendered on a particular route. Essentially the frontend will act as a sort of mini-browser.

By limiting interactions in this way we effectively circumventing a lot of security concerns that would arise otherwise while promoting code reuse and writing generic modules that will be useful for other members.

It's still early days (the process of joining is in design stage), but if it sounds intriguing to you, feel free to contact me🙂

Here are a few screenshots demonstrating a significant "gotcha" of await import with Vite.

The one caveat is that SvelteKit can't know which of the candidates were actually imported during load.

This is significant, thank you for going into the details. In our case the list of components will contain thousands of entries at the very least, so including anything unnecessary in the bundle won't work.